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
This commit is contained in:
ridiculousfish
2012-06-04 14:20:01 -07:00
parent cc90f9cf80
commit 69446be1ee
9 changed files with 104 additions and 57 deletions

View File

@@ -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 )