diff options
-rw-r--r-- | libc/stdlib/abort.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c index dfb50e2f6..276ccf1a6 100644 --- a/libc/stdlib/abort.c +++ b/libc/stdlib/abort.c @@ -18,6 +18,8 @@ Cambridge, MA 02139, USA. */ /* Hacked up for uClibc by Erik Andersen */ +#define _GNU_SOURCE +#include <features.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -50,11 +52,26 @@ extern void weak_function _stdio_term(void); extern void _exit __P((int __status)) __attribute__ ((__noreturn__)); static int been_there_done_that = 0; +/* Be prepared in case multiple threads try to abort(). */ +#ifdef __UCLIBC_HAS_THREADS__ +#include <pthread.h> +static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +# define LOCK pthread_mutex_lock(&mylock) +# define UNLOCK pthread_mutex_unlock(&mylock); +#else +# define LOCK +# define UNLOCK +#endif + + /* Cause an abnormal program termination with core-dump. */ void abort(void) { sigset_t sigset; + /* Make sure we acquire the lock before proceeding. */ + LOCK; + /* Unmask SIGABRT to be sure we can get it */ if (__sigemptyset(&sigset) == 0 && __sigaddset(&sigset, SIGABRT) == 0) { sigprocmask(SIG_UNBLOCK, &sigset, (sigset_t *) NULL); @@ -71,7 +88,9 @@ void abort(void) /* Try to suicide with a SIGABRT. */ if (been_there_done_that == 0) { been_there_done_that++; + UNLOCK; raise(SIGABRT); + LOCK; } /* Still here? Try to remove any signal handlers. */ |