mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-06 17:31:14 -03:00
Various updates to signal event handling
darcs-hash:20051006115416-ac50b-ab0a1be946f758cfdeaa5dfe172f417acb9b6e79.gz
This commit is contained in:
55
builtin.c
55
builtin.c
@@ -800,11 +800,24 @@ static int builtin_function( wchar_t **argv )
|
|||||||
|
|
||||||
case 's':
|
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 )
|
if( !e )
|
||||||
die_mem();
|
die_mem();
|
||||||
e->type = EVENT_SIGNAL;
|
e->type = EVENT_SIGNAL;
|
||||||
e->signal = wcs2sig( woptarg );
|
e->signal = sig;
|
||||||
e->function_name=0;
|
e->function_name=0;
|
||||||
al_push( events, e );
|
al_push( events, e );
|
||||||
break;
|
break;
|
||||||
@@ -812,7 +825,19 @@ static int builtin_function( wchar_t **argv )
|
|||||||
|
|
||||||
case 'v':
|
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 )
|
if( !e )
|
||||||
die_mem();
|
die_mem();
|
||||||
e->type = EVENT_VARIABLE;
|
e->type = EVENT_VARIABLE;
|
||||||
@@ -824,11 +849,29 @@ static int builtin_function( wchar_t **argv )
|
|||||||
|
|
||||||
case 'x':
|
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 )
|
if( !e )
|
||||||
die_mem();
|
die_mem();
|
||||||
e->type = EVENT_EXIT;
|
e->type = EVENT_EXIT;
|
||||||
e->pid = wcstol( woptarg, 0, 10 );
|
e->pid = pid;
|
||||||
e->function_name=0;
|
e->function_name=0;
|
||||||
al_push( events, e );
|
al_push( events, e );
|
||||||
break;
|
break;
|
||||||
@@ -916,7 +959,7 @@ static int builtin_function( wchar_t **argv )
|
|||||||
|
|
||||||
al_foreach( events, (void (*)(const void *))&event_free );
|
al_foreach( events, (void (*)(const void *))&event_free );
|
||||||
al_destroy( events );
|
al_destroy( events );
|
||||||
|
free( events );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
64
event.c
64
event.c
@@ -131,20 +131,24 @@ void event_add_handler( event_t *event )
|
|||||||
if( !events )
|
if( !events )
|
||||||
events = al_new();
|
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 );
|
al_push( events, e );
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_remove( event_t *criterion )
|
void event_remove( event_t *criterion )
|
||||||
{
|
{
|
||||||
int i;
|
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
|
Because of concurrency issues, env_remove does not actually free
|
||||||
anything - instead it simply moves all events that should be
|
any events - instead it simply moves all events that should be
|
||||||
removed to the killme list.
|
removed from the event list to the killme list.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if( !events )
|
if( !events )
|
||||||
@@ -159,30 +163,56 @@ void event_remove( event_t *criterion )
|
|||||||
killme = al_new();
|
killme = al_new();
|
||||||
|
|
||||||
al_push( killme, n );
|
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
|
else
|
||||||
{
|
{
|
||||||
|
if( !new_list )
|
||||||
|
new_list = al_new();
|
||||||
al_push( new_list, n );
|
al_push( new_list, n );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
al_destroy( events );
|
al_destroy( events );
|
||||||
|
free( events );
|
||||||
events = new_list;
|
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 i;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
if( !events )
|
if( !events )
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
for( i=0; i<al_get_count( events); i++ )
|
for( i=0; i<al_get_count( events); i++ )
|
||||||
{
|
{
|
||||||
event_t *n = (event_t *)al_get( events, i );
|
event_t *n = (event_t *)al_get( events, i );
|
||||||
if( event_match(criterion, n ) )
|
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++ )
|
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 );
|
event_free( roadkill );
|
||||||
}
|
}
|
||||||
al_truncate( killme, 0 );
|
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;
|
string_buffer_t *b=0;
|
||||||
array_list_t *fire=0;
|
array_list_t *fire=0;
|
||||||
|
|
||||||
if( !events )
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
First we free all events that have been removed
|
First we free all events that have been removed
|
||||||
*/
|
*/
|
||||||
event_free_kills();
|
event_free_kills();
|
||||||
|
|
||||||
|
if( !events )
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Then we iterate over all events, adding events that should be
|
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
|
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_foreach( events, (void (*)(const void *))&event_free );
|
||||||
al_destroy( events );
|
al_destroy( events );
|
||||||
|
free( events );
|
||||||
events=0;
|
events=0;
|
||||||
}
|
}
|
||||||
if( killme )
|
if( killme )
|
||||||
{
|
{
|
||||||
al_foreach( killme, (void (*)(const void *))&event_free );
|
al_foreach( killme, (void (*)(const void *))&event_free );
|
||||||
al_destroy( killme );
|
al_destroy( killme );
|
||||||
|
free( killme );
|
||||||
killme=0;
|
killme=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_free( event_t *e )
|
void event_free( event_t *e )
|
||||||
{
|
{
|
||||||
free( e->function_name );
|
free( (void *)e->function_name );
|
||||||
if( e->type == EVENT_VARIABLE )
|
if( e->type == EVENT_VARIABLE )
|
||||||
free( e->variable );
|
free( (void *)e->variable );
|
||||||
free( e );
|
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
|
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 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
|
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. */
|
/* Set the handling for job control signals back to the default. */
|
||||||
signal (SIGINT, SIG_DFL);
|
signal_reset_handlers();
|
||||||
signal (SIGQUIT, SIG_DFL);
|
|
||||||
signal (SIGTSTP, SIG_DFL);
|
|
||||||
signal (SIGTTIN, SIG_DFL);
|
|
||||||
signal (SIGTTOU, SIG_DFL);
|
|
||||||
signal (SIGCHLD, SIG_DFL);
|
|
||||||
|
|
||||||
sigset_t chldset;
|
sigset_t chldset;
|
||||||
sigemptyset( &chldset );
|
sigemptyset( &chldset );
|
||||||
|
|||||||
1
parser.c
1
parser.c
@@ -212,6 +212,7 @@ void parser_pop_block()
|
|||||||
free( current_block->function_description );
|
free( current_block->function_description );
|
||||||
al_foreach( current_block->function_events,
|
al_foreach( current_block->function_events,
|
||||||
(void (*)(const void *))&event_free );
|
(void (*)(const void *))&event_free );
|
||||||
|
al_destroy( current_block->function_events );
|
||||||
free( current_block->function_events );
|
free( current_block->function_events );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
64
signal.c
64
signal.c
@@ -12,8 +12,11 @@ The library for various signal related issues
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "wutil.h"
|
||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
@@ -250,7 +253,9 @@ static int match_signal_name( const wchar_t *canonical,
|
|||||||
|
|
||||||
int wcs2sig( const wchar_t *str )
|
int wcs2sig( const wchar_t *str )
|
||||||
{
|
{
|
||||||
int i;
|
int i, res;
|
||||||
|
wchar_t *end=0;
|
||||||
|
|
||||||
for( i=0; lookup[i].desc ; i++ )
|
for( i=0; lookup[i].desc ; i++ )
|
||||||
{
|
{
|
||||||
if( match_signal_name( lookup[i].name, str) )
|
if( match_signal_name( lookup[i].name, str) )
|
||||||
@@ -258,6 +263,11 @@ int wcs2sig( const wchar_t *str )
|
|||||||
return lookup[i].signal;
|
return lookup[i].signal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
errno=0;
|
||||||
|
res = wcstol( str, &end, 10 );
|
||||||
|
if( !errno && end && !*end )
|
||||||
|
return res;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,6 +328,31 @@ static void handle_int( int sig, siginfo_t *info, void *context )
|
|||||||
default_handler( sig, info, 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.
|
Sets appropriate signal handlers.
|
||||||
*/
|
*/
|
||||||
@@ -338,7 +373,6 @@ void signal_set_handlers()
|
|||||||
sigaction( SIGTTIN, &act, 0);
|
sigaction( SIGTTIN, &act, 0);
|
||||||
sigaction( SIGTTOU, &act, 0);
|
sigaction( SIGTTOU, &act, 0);
|
||||||
sigaction( SIGCHLD, &act, 0);
|
sigaction( SIGCHLD, &act, 0);
|
||||||
sigaction( SIGALRM, &act, 0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Ignore sigpipe, it is generated if fishd dies, but we can
|
Ignore sigpipe, it is generated if fishd dies, but we can
|
||||||
@@ -348,7 +382,6 @@ void signal_set_handlers()
|
|||||||
|
|
||||||
if( is_interactive )
|
if( is_interactive )
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Interactive mode. Ignore interactive signals. We are a
|
Interactive mode. Ignore interactive signals. We are a
|
||||||
shell, we know whats best for the user. ;-)
|
shell, we know whats best for the user. ;-)
|
||||||
@@ -370,7 +403,7 @@ void signal_set_handlers()
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
act.sa_sigaction = &job_handle_signal;
|
act.sa_sigaction = &handle_chld;
|
||||||
act.sa_flags = SA_SIGINFO;
|
act.sa_flags = SA_SIGINFO;
|
||||||
if( sigaction( SIGCHLD, &act, 0) )
|
if( sigaction( SIGCHLD, &act, 0) )
|
||||||
{
|
{
|
||||||
@@ -400,7 +433,7 @@ void signal_set_handlers()
|
|||||||
|
|
||||||
act.sa_handler=SIG_DFL;
|
act.sa_handler=SIG_DFL;
|
||||||
|
|
||||||
act.sa_sigaction = &job_handle_signal;
|
act.sa_sigaction = &handle_chld;
|
||||||
act.sa_flags = SA_SIGINFO;
|
act.sa_flags = SA_SIGINFO;
|
||||||
if( sigaction( SIGCHLD, &act, 0) )
|
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 );
|
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();
|
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 );
|
||||||
|
|||||||
Reference in New Issue
Block a user