diff options
author | 2012-06-04 14:20:01 -0700 | |
---|---|---|
committer | 2012-06-04 14:20:01 -0700 | |
commit | 69446be1ee063771f2e0b498a50f9b0787ea70c7 (patch) | |
tree | be5ecf3a473052475218df605d350a204666c750 /event.cpp | |
parent | cc90f9cf803bc4aba928b2a80be451d9b717c5f0 (diff) |
Signal handling cleanup and improved safety
Fixes issue where you couldn't control-C out of a loop (https://github.com/ridiculousfish/fishfish/issues/13)
Also stops doing memory allocation in the signal handler (oops) https://github.com/ridiculousfish/fishfish/issues/27
Diffstat (limited to 'event.cpp')
-rw-r--r-- | event.cpp | 69 |
1 files changed, 51 insertions, 18 deletions
@@ -66,7 +66,8 @@ static int active_list=0; typedef std::vector<event_t *> event_list_t; /** - List of event handlers + List of event handlers. + Note this is inspected by our signal handler, so we must block signals around manipulating it. */ static event_list_t events; /** @@ -246,8 +247,11 @@ void event_add_handler( const event_t *event ) { signal_handle( e->param1.signal, 1 ); } - - events.push_back(e); + + // Block around updating the events vector + signal_block(); + events.push_back(e); + signal_unblock(); } void event_remove( event_t *criterion ) @@ -296,7 +300,9 @@ void event_remove( event_t *criterion ) new_list.push_back(n); } } + signal_block(); events.swap(new_list); + signal_unblock(); } int event_get( event_t *criterion, std::vector<event_t *> *out ) @@ -322,6 +328,28 @@ int event_get( event_t *criterion, std::vector<event_t *> *out ) return found; } +bool event_is_signal_observed(int sig) +{ + /* We are in a signal handler! Don't allocate memory, etc. + This does what event_match does, except it doesn't require passing in an event_t. + */ + size_t i, max = events.size(); + for (i=0; i < max; i++) + { + const event_t *event = events[i]; + if (event->type == EVENT_ANY) + { + return true; + } + else if (event->type == EVENT_SIGNAL) + { + if( event->param1.signal == EVENT_ANY_SIGNAL || event->param1.signal == sig) + return true; + } + } + return false; +} + /** Free all events in the kill list */ @@ -519,26 +547,32 @@ static void event_fire_delayed() } } +void event_fire_signal(int signal) +{ + /* + This means we are in a signal handler. We must be very + careful not do do anything that could cause a memory + allocation or something else that might be bad when in a + signal handler. + */ + if( sig_list[active_list].count < SIG_UNHANDLED_MAX ) + sig_list[active_list].signal[sig_list[active_list].count++]=signal; + else + sig_list[active_list].overflow=1; +} + void event_fire( event_t *event ) { - is_event++; if( event && (event->type == EVENT_SIGNAL) ) { - /* - This means we are in a signal handler. We must be very - careful not do do anything that could cause a memory - allocation or something else that might be bad when in a - signal handler. - */ - if( sig_list[active_list].count < SIG_UNHANDLED_MAX ) - sig_list[active_list].signal[sig_list[active_list].count++]=event->param1.signal; - else - sig_list[active_list].overflow=1; + event_fire_signal(event->param1.signal); } else { + is_event++; + /* Fire events triggered by signals */ @@ -555,9 +589,8 @@ void event_fire( event_t *event ) event_fire_internal( event ); } } - + is_event--; } - is_event--; } @@ -569,10 +602,10 @@ void event_destroy() { for_each(events.begin(), events.end(), event_free); - events.resize(0); + events.clear(); for_each(killme.begin(), killme.end(), event_free); - killme.resize(0); + killme.clear(); } void event_free( event_t *e ) |