Various updates to signal event handling

darcs-hash:20051006115416-ac50b-ab0a1be946f758cfdeaa5dfe172f417acb9b6e79.gz
This commit is contained in:
axel 2005-10-06 21:54:16 +10:00
parent 3b02b76c79
commit 2ac6b62df2
7 changed files with 175 additions and 34 deletions

View file

@ -800,11 +800,24 @@ static int builtin_function( wchar_t **argv )
case 's':
{
event_t *e = malloc( sizeof(event_t));
int sig = wcs2sig( woptarg );
event_t *e;
if( sig < 0 )
{
sb_printf( sb_err,
L"%ls: Unknown signal %ls\n",
argv[0],
woptarg );
res=1;
break;
}
e = malloc( sizeof(event_t));
if( !e )
die_mem();
e->type = EVENT_SIGNAL;
e->signal = wcs2sig( woptarg );
e->signal = sig;
e->function_name=0;
al_push( events, e );
break;
@ -812,7 +825,19 @@ static int builtin_function( wchar_t **argv )
case 'v':
{
event_t *e = malloc( sizeof(event_t));
event_t *e;
if( !wcsvarname( woptarg ) )
{
sb_printf( sb_err,
L"%ls: Invalid variable name %ls\n",
argv[0],
woptarg );
res=1;
break;
}
e = malloc( sizeof(event_t));
if( !e )
die_mem();
e->type = EVENT_VARIABLE;
@ -824,11 +849,29 @@ static int builtin_function( wchar_t **argv )
case 'x':
{
event_t *e = malloc( sizeof(event_t));
pid_t pid;
wchar_t *end;
event_t *e;
errno = 0;
pid = wcstol( woptarg, &end, 10 );
if( errno || !end || *end )
{
sb_printf( sb_err,
L"%ls: Invalid process id %ls\n",
argv[0],
woptarg );
res=1;
break;
}
e = malloc( sizeof(event_t));
if( !e )
die_mem();
e->type = EVENT_EXIT;
e->pid = wcstol( woptarg, 0, 10 );
e->pid = pid;
e->function_name=0;
al_push( events, e );
break;
@ -916,7 +959,7 @@ static int builtin_function( wchar_t **argv )
al_foreach( events, (void (*)(const void *))&event_free );
al_destroy( events );
free( events );
}
else
{

58
event.c
View file

@ -131,7 +131,10 @@ void event_add_handler( event_t *event )
if( !events )
events = al_new();
debug( 1, L"add event of type %d", e->type );
if( e->type == EVENT_SIGNAL )
{
signal_handle( e->signal, 1 );
}
al_push( events, e );
}
@ -139,12 +142,13 @@ void event_add_handler( event_t *event )
void event_remove( event_t *criterion )
{
int i;
array_list_t *new_list = al_new();
array_list_t *new_list=0;
event_t e;
/*
Because of concurrency issues, env_remove does not actually free
anything - instead it simply moves all events that should be
removed to the killme list.
any events - instead it simply moves all events that should be
removed from the event list to the killme list.
*/
if( !events )
@ -159,30 +163,56 @@ void event_remove( event_t *criterion )
killme = al_new();
al_push( killme, n );
/*
If this event was a signal handler and no other handler handles
the specified signal type, do not handle that type of signal any
more.
*/
if( n->type == EVENT_SIGNAL )
{
e.type = EVENT_SIGNAL;
e.signal = n->signal;
e.function_name = 0;
if( event_get( &e, 0 ) == 1 )
{
signal_handle( e.signal, 0 );
}
}
}
else
{
if( !new_list )
new_list = al_new();
al_push( new_list, n );
}
}
al_destroy( events );
free( events );
events = new_list;
}
void event_get( event_t *criterion, array_list_t *out )
int event_get( event_t *criterion, array_list_t *out )
{
int i;
int found = 0;
if( !events )
return;
return 0;
for( i=0; i<al_get_count( events); i++ )
{
event_t *n = (event_t *)al_get( events, i );
if( event_match(criterion, n ) )
{
found++;
if( out )
al_push( out, n );
}
}
return found;
}
/**
@ -196,7 +226,7 @@ static void event_free_kills()
for( i=0; i<al_get_count( killme ); i++ )
{
event_t *roadkill = (event_t *)al_get( events, i );
event_t *roadkill = (event_t *)al_get( killme, i );
event_free( roadkill );
}
al_truncate( killme, 0 );
@ -233,14 +263,14 @@ static void event_fire_internal( event_t *event, array_list_t *arguments )
string_buffer_t *b=0;
array_list_t *fire=0;
if( !events )
return;
/*
First we free all events that have been removed
*/
event_free_kills();
if( !events )
return;
/*
Then we iterate over all events, adding events that should be
fired to a second list. We need to do this in a separate step
@ -408,21 +438,23 @@ void event_destroy()
{
al_foreach( events, (void (*)(const void *))&event_free );
al_destroy( events );
free( events );
events=0;
}
if( killme )
{
al_foreach( killme, (void (*)(const void *))&event_free );
al_destroy( killme );
free( killme );
killme=0;
}
}
void event_free( event_t *e )
{
free( e->function_name );
free( (void *)e->function_name );
if( e->type == EVENT_VARIABLE )
free( e->variable );
free( (void *)e->variable );
free( e );
}

View file

@ -74,8 +74,11 @@ void event_remove( event_t *event );
Return all events which match the specified event class
\param criterion Is the class of events to return. If the criterion has a non-null function_name, only events which trigger the specified function will return.
\param out the list to add events to. May be 0, in which case no events will be added, but the result count will still be valid
\return the number of found matches
*/
void event_get( event_t *criterion, array_list_t *out );
int event_get( event_t *criterion, array_list_t *out );
/**
Fire the specified event. The function_name field of the event must

7
exec.c
View file

@ -391,12 +391,7 @@ static void setup_child_process( job_t *j )
}
/* Set the handling for job control signals back to the default. */
signal (SIGINT, SIG_DFL);
signal (SIGQUIT, SIG_DFL);
signal (SIGTSTP, SIG_DFL);
signal (SIGTTIN, SIG_DFL);
signal (SIGTTOU, SIG_DFL);
signal (SIGCHLD, SIG_DFL);
signal_reset_handlers();
sigset_t chldset;
sigemptyset( &chldset );

View file

@ -212,6 +212,7 @@ void parser_pop_block()
free( current_block->function_description );
al_foreach( current_block->function_events,
(void (*)(const void *))&event_free );
al_destroy( current_block->function_events );
free( current_block->function_events );
break;
}

View file

@ -12,8 +12,11 @@ The library for various signal related issues
#include <signal.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#include "common.h"
#include "util.h"
#include "wutil.h"
#include "signal.h"
#include "event.h"
#include "reader.h"
@ -250,7 +253,9 @@ static int match_signal_name( const wchar_t *canonical,
int wcs2sig( const wchar_t *str )
{
int i;
int i, res;
wchar_t *end=0;
for( i=0; lookup[i].desc ; i++ )
{
if( match_signal_name( lookup[i].name, str) )
@ -258,6 +263,11 @@ int wcs2sig( const wchar_t *str )
return lookup[i].signal;
}
}
errno=0;
res = wcstol( str, &end, 10 );
if( !errno && end && !*end )
return res;
return -1;
}
@ -318,6 +328,31 @@ static void handle_int( int sig, siginfo_t *info, void *context )
default_handler( sig, info, context);
}
/**
sigchld handler. Does notification and calls the handler in proc.c
*/
static void handle_chld( int sig, siginfo_t *info, void *context )
{
job_handle_signal( sig, info, context );
default_handler( sig, info, context);
}
void signal_reset_handlers()
{
int i;
struct sigaction act;
sigemptyset( & act.sa_mask );
act.sa_flags=0;
act.sa_handler=SIG_DFL;
for( i=0; lookup[i].desc ; i++ )
{
sigaction( lookup[i].signal, &act, 0);
}
}
/**
Sets appropriate signal handlers.
*/
@ -338,7 +373,6 @@ void signal_set_handlers()
sigaction( SIGTTIN, &act, 0);
sigaction( SIGTTOU, &act, 0);
sigaction( SIGCHLD, &act, 0);
sigaction( SIGALRM, &act, 0);
/*
Ignore sigpipe, it is generated if fishd dies, but we can
@ -348,7 +382,6 @@ void signal_set_handlers()
if( is_interactive )
{
/*
Interactive mode. Ignore interactive signals. We are a
shell, we know whats best for the user. ;-)
@ -370,7 +403,7 @@ void signal_set_handlers()
exit(1);
}
act.sa_sigaction = &job_handle_signal;
act.sa_sigaction = &handle_chld;
act.sa_flags = SA_SIGINFO;
if( sigaction( SIGCHLD, &act, 0) )
{
@ -400,7 +433,7 @@ void signal_set_handlers()
act.sa_handler=SIG_DFL;
act.sa_sigaction = &job_handle_signal;
act.sa_sigaction = &handle_chld;
act.sa_flags = SA_SIGINFO;
if( sigaction( SIGCHLD, &act, 0) )
{
@ -410,3 +443,24 @@ void signal_set_handlers()
}
}
void signal_handle( int sig, int do_handle )
{
struct sigaction act;
/*
These should always be handled
*/
if( (sig == SIGINT) ||
(sig == SIGQUIT) ||
(sig == SIGTSTP) ||
(sig == SIGTTIN) ||
(sig == SIGTTOU) ||
(sig == SIGCHLD) )
return;
sigemptyset( & act.sa_mask );
act.sa_flags=SA_SIGINFO;
act.sa_sigaction = (do_handle?&default_handler:SIG_DFL);
sigaction( sig, &act, 0);
}

View file

@ -20,4 +20,17 @@ const wchar_t *sig2wcs( int sig );
*/
const wchar_t *sig_description( int sig );
/**
Set all signal handlers to SIG_DFL
*/
void signal_reset_handlers();
/**
Set signal handlers to fish default handlers
*/
void signal_set_handlers();
/**
Tell fish to catch the specified signal and fire an event, instead of performing the default action
*/
void signal_handle( int sig, int do_handle );