mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-25 20:33:08 +00:00
Various updates to signal event handling
darcs-hash:20051006115416-ac50b-ab0a1be946f758cfdeaa5dfe172f417acb9b6e79.gz
This commit is contained in:
parent
3b02b76c79
commit
2ac6b62df2
7 changed files with 175 additions and 34 deletions
55
builtin.c
55
builtin.c
|
@ -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
|
||||
{
|
||||
|
|
64
event.c
64
event.c
|
@ -131,20 +131,24 @@ 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 );
|
||||
}
|
||||
|
||||
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 ) )
|
||||
al_push( out, 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 );
|
||||
}
|
||||
|
||||
|
|
5
event.h
5
event.h
|
@ -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
7
exec.c
|
@ -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 );
|
||||
|
|
1
parser.c
1
parser.c
|
@ -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;
|
||||
}
|
||||
|
|
64
signal.c
64
signal.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
13
signal.h
13
signal.h
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue