summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/stdlib/abort.c19
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. */