diff options
| author | Eric Andersen <andersen@codepoet.org> | 2001-11-21 14:46:32 +0000 | 
|---|---|---|
| committer | Eric Andersen <andersen@codepoet.org> | 2001-11-21 14:46:32 +0000 | 
| commit | 4248737d6d674ca07d9264419a902a87355c09c6 (patch) | |
| tree | 5bb8fa2ae100f598d788dde41f21276e7bdf92c1 /libc/stdlib | |
| parent | 14f7d9c3fd3fe0898e7479684a3733975101c290 (diff) | |
Cleanup abort() so it behaves itself a bit better
Diffstat (limited to 'libc/stdlib')
| -rw-r--r-- | libc/stdlib/abort.c | 75 | 
1 files changed, 65 insertions, 10 deletions
diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c index 7b7d6bb50..53abbd284 100644 --- a/libc/stdlib/abort.c +++ b/libc/stdlib/abort.c @@ -21,31 +21,86 @@ Cambridge, MA 02139, USA.  */  #include <signal.h>  #include <stdio.h>  #include <stdlib.h> +#include <string.h>  #include <unistd.h>  #include <signal.h>  #include <errno.h> + +/* Our last ditch effort to commit suicide */  +#if defined(__i386__) +#define ABORT_INSTRUCTION asm ("hlt") +#elif defined(__ia64__) +#define ABORT_INSTRUCTION asm ("break 0") +#elif defined(__mc68000__) +#define ABORT_INSTRUCTION asm ("illegal") +#elif defined(__mips__) +#define ABORT_INSTRUCTION asm ("break 255") +#elif defined(__s390__) +#define ABORT_INSTRUCTION asm (".word 0") +#elif defined(__sparc__) +#define ABORT_INSTRUCTION asm ("unimp 0xf00") +#elif defined(__x86_64__) +#define ABORT_INSTRUCTION asm ("hlt") +#else +#define ABORT_INSTRUCTION +#endif +  typedef void (*vfuncp) (void);  extern vfuncp __uClibc_cleanup;  extern void _exit __P((int __status)) __attribute__ ((__noreturn__)); +static int been_there_done_that = 0;  /* Cause an abnormal program termination with core-dump.  */  void abort(void)  { -	sigset_t sigset; +    sigset_t sigset; + +    /* Unmask SIGABRT to be sure we can get it */ +    if (__sigemptyset(&sigset) == 0 && __sigaddset(&sigset, SIGABRT) == 0) { +	sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *) NULL); +    } + +    /* __uClibc_cleanup NULLs itself out after being called */ +    if (__uClibc_cleanup) {		 +	__uClibc_cleanup(); +    } + +    while (1) { +	/* Try to suicide with a SIGABRT.  */ +	if (been_there_done_that == 0) { +	    been_there_done_that++; +	    raise(SIGABRT); +	} + +	/* Still here?  Try to remove any signal handlers.  */ +	if (been_there_done_that == 1) { +	    struct sigaction act; -	if (sigemptyset(&sigset) == 0 && sigaddset(&sigset, SIGABRT) == 0) { -		sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *) NULL); +	    been_there_done_that++; +	    memset (&act, '\0', sizeof (struct sigaction)); +	    act.sa_handler = SIG_DFL; +	    __sigfillset (&act.sa_mask); +	    act.sa_flags = 0; +	    sigaction (SIGABRT, &act, NULL);  	} -	if (__uClibc_cleanup) {		/* Not already executing __uClibc_cleanup. */ -		__uClibc_cleanup(); +	/* Still here?  Try to suicide with an illegal instruction */ +	if (been_there_done_that == 2) { +	    been_there_done_that++; +	    ABORT_INSTRUCTION;  	} +	/* Still here?  Try to at least exit */ +	if (been_there_done_that == 3) { +	    been_there_done_that++; +	    _exit (127); +	} + +	/* Still here?  We're screwed.  Sleepy time.  Good night */  	while (1) -		if (raise(SIGABRT)) -			/* If we can't signal ourselves, exit.  */ -			_exit(127); -	/* If we signal ourselves and are still alive, -	   or can't exit, loop forever.  */ +	    /* Try for ever and ever.  */ +	    ABORT_INSTRUCTION; +    }  } +  | 
