aboutsummaryrefslogtreecommitdiffhomepage
path: root/event.cpp
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2012-06-04 14:20:01 -0700
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2012-06-04 14:20:01 -0700
commit69446be1ee063771f2e0b498a50f9b0787ea70c7 (patch)
treebe5ecf3a473052475218df605d350a204666c750 /event.cpp
parentcc90f9cf803bc4aba928b2a80be451d9b717c5f0 (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.cpp69
1 files changed, 51 insertions, 18 deletions
diff --git a/event.cpp b/event.cpp
index 33b32daa..368f2d6c 100644
--- a/event.cpp
+++ b/event.cpp
@@ -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 )