summaryrefslogtreecommitdiff
path: root/sysdeps/generic/abort.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/generic/abort.c')
-rw-r--r--sysdeps/generic/abort.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/sysdeps/generic/abort.c b/sysdeps/generic/abort.c
index 366a543791..14c182b411 100644
--- a/sysdeps/generic/abort.c
+++ b/sysdeps/generic/abort.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1993, 1995, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,11 +20,12 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
/* Try to get a machine dependent instruction which will make the
program crash. This is used in case everything else fails. */
-#include "abort-instr.h"
+#include <abort-instr.h>
#ifndef ABORT_INSTRUCTION
/* No such instruction is available. */
# define ABORT_INSTRUCTION
@@ -46,7 +47,7 @@ abort (void)
sigset_t sigs;
/* First acquire the lock. */
- __libc_lock_lock (lock);
+ __libc_lock_lock_recursive (lock);
/* Now it's for sure we are alone. But recursive calls are possible. */
@@ -70,8 +71,19 @@ abort (void)
/* Send signal which possibly calls a user handler. */
if (stage == 2)
{
- ++stage;
+ /* This stage is special: we must allow repeated calls of
+ `abort' when a user defined handler for SIGABRT is installed.
+ This is risky since the `raise' implementation might also
+ fail but I don't see another possiblity. */
+ int save_stage = stage;
+
+ stage = 0;
+ __libc_lock_unlock_recursive (lock);
+
raise (SIGABRT);
+
+ __libc_lock_lock_recursive (lock);
+ stage = save_stage + 1;
}
/* There was a handler installed. Now remove it. */