From 9c2c44b0086556b526e7229db7ef1ddff520d698 Mon Sep 17 00:00:00 2001 From: Olaf Barthel Date: Sun, 27 Mar 2005 10:02:50 +0000 Subject: [PATCH] - raise() no longer resets the signal handler before it invokes the one currently configured. It merely blocks the delivery of the respective signal to prevent recursion. - raise() now drops into abort() if a signal handler is set to SIG_DFL. The exception is in SIGINT delivery, which has the effect of printing a different termination message but otherwise program flow takes the same path as abort(). git-svn-id: file:///Users/olsen/Code/migration-svn-zu-git/logical-line-staging/clib2/trunk@14907 87f5fb63-7c3d-0410-a384-fd976d0f7a62 --- library/changes | 9 ++++ library/signal_kill.c | 68 ++++++++++-------------------- library/signal_raise.c | 87 +++++++++++++++++++++++++-------------- library/stdio_init_exit.c | 4 +- library/stdlib_abort.c | 10 +++-- library/unistd_chdir.c | 3 +- library/unistd_sleep.c | 3 +- library/unistd_unlink.c | 3 +- 8 files changed, 101 insertions(+), 86 deletions(-) diff --git a/library/changes b/library/changes index a4f4641..850fb6d 100644 --- a/library/changes +++ b/library/changes @@ -6,6 +6,15 @@ This makes it possible to override the default definition of the __check_abort_enabled variable in your own programs. +- raise() no longer resets the signal handler before it invokes the one + currently configured. It merely blocks the delivery of the respective + signal to prevent recursion. + +- raise() now drops into abort() if a signal handler is set to + SIG_DFL. The exception is in SIGINT delivery, which has the + effect of printing a different termination message but otherwise + program flow takes the same path as abort(). + c.lib 1.190 (25.3.2005) diff --git a/library/signal_kill.c b/library/signal_kill.c index 2e62e2a..f9514b7 100644 --- a/library/signal_kill.c +++ b/library/signal_kill.c @@ -1,5 +1,5 @@ /* - * $Id: signal_kill.c,v 1.4 2005-02-03 16:56:15 obarthel Exp $ + * $Id: signal_kill.c,v 1.5 2005-03-27 10:02:50 obarthel Exp $ * * :ts=4 * @@ -55,58 +55,34 @@ kill(pid_t pid, int signal_number) if(pid > 0) { - #if 0 + ULONG max_cli_number,i; + BOOL found = FALSE; + + max_cli_number = MaxCli(); + + for(i = 1 ; i <= max_cli_number ; i++) { - struct Process * cli_process; - - cli_process = FindCliProc((ULONG)pid); - if(cli_process == NULL) + if(FindCliProc(i) == (struct Process *)pid) { - SHOWMSG("didn't find the process"); - - __set_errno(ESRCH); - goto out; + found = TRUE; + break; } - - SHOWMSG("found the process"); - - if(signal_number == SIGTERM || signal_number == SIGINT) - Signal((struct Task *)cli_process,SIGBREAKF_CTRL_C); - else - SHOWMSG("but won't shut it down"); } - #else + + if(NOT found) { - ULONG max_cli_number,i; - BOOL found = FALSE; + SHOWMSG("didn't find the process"); - max_cli_number = MaxCli(); - - for(i = 1 ; i <= max_cli_number ; i++) - { - if(FindCliProc(i) == (struct Process *)pid) - { - found = TRUE; - break; - } - } - - if(NOT found) - { - SHOWMSG("didn't find the process"); - - __set_errno(ESRCH); - goto out; - } - - SHOWMSG("found the process"); - - if(signal_number == SIGTERM || signal_number == SIGINT) - Signal((struct Task *)pid,SIGBREAKF_CTRL_C); - else - SHOWMSG("but won't shut it down"); + __set_errno(ESRCH); + goto out; } - #endif + + SHOWMSG("found the process"); + + if(signal_number == SIGTERM || signal_number == SIGINT) + Signal((struct Task *)pid,SIGBREAKF_CTRL_C); + else + SHOWMSG("but won't shut it down"); } result = 0; diff --git a/library/signal_raise.c b/library/signal_raise.c index 044f4b3..28c594b 100644 --- a/library/signal_raise.c +++ b/library/signal_raise.c @@ -1,5 +1,5 @@ /* - * $Id: signal_raise.c,v 1.5 2005-03-26 11:01:13 obarthel Exp $ + * $Id: signal_raise.c,v 1.6 2005-03-27 10:02:50 obarthel Exp $ * * :ts=4 * @@ -37,18 +37,22 @@ /****************************************************************************/ +/* This table holds pointers to all signal handlers configured at a time. */ signal_handler_t __signal_handler_table[NUM_SIGNALS] = { - SIG_DFL, - SIG_DFL, - SIG_DFL, - SIG_DFL, - SIG_DFL, - SIG_DFL + SIG_DFL, /* SIGABRT */ + SIG_DFL, /* SIGFPE */ + SIG_DFL, /* SIGILL */ + SIG_DFL, /* SIGINT */ + SIG_DFL, /* SIGSEGV */ + SIG_DFL /* SIGTERM */ }; /****************************************************************************/ +/* This holds a mask of all signals whose delivery is currently blocked. + The sigaddset(), sigblock(), sigprocmask() and sigsetmask() functions + modify or query it. */ int __signals_blocked; /****************************************************************************/ @@ -56,6 +60,8 @@ int __signals_blocked; int raise(int sig) { + static int local_signals_blocked; + int result = -1; ENTER(); @@ -64,6 +70,7 @@ raise(int sig) assert( SIGABRT <= sig && sig <= SIGTERM ); + /* This has to be a well-known and supported signal. */ if(sig < SIGABRT || sig > SIGTERM) { SHOWMSG("unknown signal number"); @@ -72,43 +79,61 @@ raise(int sig) goto out; } - if(FLAG_IS_CLEAR(__signals_blocked,(1 << sig))) + /* Can we deliver the signal? */ + if(FLAG_IS_CLEAR(__signals_blocked, (1 << sig)) && + FLAG_IS_CLEAR(local_signals_blocked, (1 << sig))) { - int table_entry = sig - SIGABRT; signal_handler_t handler; - handler = __signal_handler_table[table_entry]; + /* Which handler is installed for this signal? */ + handler = __signal_handler_table[sig - SIGABRT]; - /* Revert to the default handler to prevent recursion. */ - __signal_handler_table[table_entry] = SIG_DFL; - - if(handler == SIG_DFL) + /* Should we ignore this signal? */ + if(handler != SIG_IGN) { - char break_string[80]; + /* Block delivery of this signal to prevent recursion. */ + SET_FLAG(local_signals_blocked,(1 << sig)); - SHOWMSG("this is the default handler"); + /* The default behaviour is to drop into abort(), or do + something very much like it. */ + if(handler == SIG_DFL) + { + SHOWMSG("this is the default handler"); - /* Don't trigger a recursion. */ - __check_abort_enabled = FALSE; + if(sig == SIGINT) + { + char break_string[80]; - Fault(ERROR_BREAK,NULL,break_string,(LONG)sizeof(break_string)); + /* Turn off ^C checking for good. */ + __check_abort_enabled = FALSE; - __print_termination_message((sig == SIGINT) ? break_string : NULL); + Fault(ERROR_BREAK,NULL,break_string,(LONG)sizeof(break_string)); - SHOWMSG("bye, bye..."); + __print_termination_message(break_string); - /* Note that we drop into the exit() function which - * does not trigger the exit trap. - */ - _exit(EXIT_FAILURE); - } - else if (handler != SIG_IGN) - { - SHOWMSG("calling the handler"); + SHOWMSG("bye, bye..."); - (*handler)(sig); + /* Note that we drop into the exit() function which + does not trigger the exit trap. */ + _exit(EXIT_FAILURE); + } - SHOWMSG("done."); + /* Drop straight into abort(), which might call signal() + again but is otherwise guaranteed to eventually + land us in _exit(). */ + abort(); + } + else + { + SHOWMSG("calling the handler"); + + (*handler)(sig); + + SHOWMSG("done."); + } + + /* Unblock signal delivery again. */ + CLEAR_FLAG(local_signals_blocked,(1 << sig)); } } else diff --git a/library/stdio_init_exit.c b/library/stdio_init_exit.c index d7f6fb2..687c642 100644 --- a/library/stdio_init_exit.c +++ b/library/stdio_init_exit.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_init_exit.c,v 1.30 2005-03-18 12:38:23 obarthel Exp $ + * $Id: stdio_init_exit.c,v 1.31 2005-03-27 10:02:50 obarthel Exp $ * * :ts=4 * @@ -72,8 +72,6 @@ __close_all_files(void) ENTER(); - __check_abort_enabled = FALSE; - __stdio_lock(); if(__num_iob > 0) diff --git a/library/stdlib_abort.c b/library/stdlib_abort.c index db1f5f2..539a6df 100644 --- a/library/stdlib_abort.c +++ b/library/stdlib_abort.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_abort.c,v 1.3 2005-01-02 09:07:08 obarthel Exp $ + * $Id: stdlib_abort.c,v 1.4 2005-03-27 10:02:50 obarthel Exp $ * * :ts=4 * @@ -48,14 +48,18 @@ void abort(void) { + /* Try to call the signal handler that might be in charge of + handling cleanup operations, etc. */ raise(SIGABRT); + /* If the signal handler returns it means that we still have + to terminate the program. */ + __check_abort_enabled = FALSE; __print_termination_message(NULL); /* Note that we drop into the exit() function which - * does not trigger the exit trap. - */ + does not trigger the exit trap. */ _exit(EXIT_FAILURE); } diff --git a/library/unistd_chdir.c b/library/unistd_chdir.c index dd2af56..87ebf84 100644 --- a/library/unistd_chdir.c +++ b/library/unistd_chdir.c @@ -1,5 +1,5 @@ /* - * $Id: unistd_chdir.c,v 1.5 2005-02-28 10:07:32 obarthel Exp $ + * $Id: unistd_chdir.c,v 1.6 2005-03-27 10:02:50 obarthel Exp $ * * :ts=4 * @@ -47,6 +47,7 @@ /****************************************************************************/ +/* ZZZ chdir() must be reentrant according to POSIX.1 */ int chdir(const char * path_name) { diff --git a/library/unistd_sleep.c b/library/unistd_sleep.c index 9fbd35e..1cdc079 100644 --- a/library/unistd_sleep.c +++ b/library/unistd_sleep.c @@ -1,5 +1,5 @@ /* - * $Id: unistd_sleep.c,v 1.4 2005-01-02 09:07:19 obarthel Exp $ + * $Id: unistd_sleep.c,v 1.5 2005-03-27 10:02:50 obarthel Exp $ * * :ts=4 * @@ -41,6 +41,7 @@ /****************************************************************************/ +/* ZZZ sleep() must be reentrant according to POSIX.1 */ unsigned int sleep(unsigned int seconds) { diff --git a/library/unistd_unlink.c b/library/unistd_unlink.c index 846cb28..5a8d453 100644 --- a/library/unistd_unlink.c +++ b/library/unistd_unlink.c @@ -1,5 +1,5 @@ /* - * $Id: unistd_unlink.c,v 1.6 2005-03-18 12:38:25 obarthel Exp $ + * $Id: unistd_unlink.c,v 1.7 2005-03-27 10:02:50 obarthel Exp $ * * :ts=4 * @@ -53,6 +53,7 @@ /****************************************************************************/ +/* ZZZ unlink() must be reentrant according to POSIX.1 */ int unlink(const char * path_name) {