glibc/sysdeps/generic/abort.c
Roland McGrath 509d1b6842 * include/search.h: Use libc_hidden_proto for hsearch_r, lfind.
* misc/hsearch_r.c: Add libc_hidden_def.
	* misc/lsearch.c: Likewise.

	* include/ttyent.h: Use libc_hidden_proto for getttyent, setttyent,
	endttyent.
	* misc/getttyent.c: Add libc_hidden_def.

	* include/mcheck.h: Use libc_hidden_proto for mcheck.
	* malloc/mcheck.c: Add libc_hidden_def.

	* include/envz.h: Use libc_hidden_proto for envz_entry, enz_remove.
	* include/argz.h: Use libc_hidden_proto for argz_delete.
	* string/argz-delete.c: Add libc_hidden_def.
	* string/envz.c: Likewise.  Use <envz.h>, not "envz.h".

	* sysdeps/unix/sysv/linux/x86_64/clone.S (thread_start): Use
	HIDDEN_JUMPTARGET for _exit.
	* sysdeps/unix/sysv/linux/m68k/clone.S (thread_start): Likewise.
	* sysdeps/unix/sysv/linux/i386/clone.S (thread_start): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/clone.S: Likewise.
	* sysdeps/unix/_exit.S (_exit): Add libc_hidden_def.

	* include/libc-symbols.h: Fix [__ASSEMBLY__] -> [__ASSEMBLER__].
	[__ASSEMBLER__] (hidden_weak): Define using hidden_def, or to empty.
	[__ASSEMBLER__] (HIDDEN_JUMPTARGET): New macro.
	* sysdeps/unix/sysv/linux/i386/makecontext.S: Use it for exit.

	* include/stdlib.h: Use libc_hidden_proto for abort,
	__strtof_internal, __strtod_internal, __strtold_internal,
	__strtol_internal, __strtoll_internal, __strtoul_internal,
	__strtoull_internal. __strtof_l_internal, __strtod_l_internal,
	__strtold_l_internal, __strtol_l_internal, __strtoll_l_internal,
	__strtoul_l_internal, __strtoull_l_internal.
	* include/wchar.h: Use libc_hidden_proto for __wcstof_internal,
	__wcstod_internal, __wcstold_internal, __wcstol_internal,
	__wcstoll_internal, __wcstoul_internal, ____wcstof_l_internal,
	____wcstod_l_internal, ____wcstold_l_internal, ____wcstol_l_internal,
	____wcstoll_l_internal, ____wcstoul_l_internal, __wcscasecmp_l,
	__wcsncasecmp_l.
	* sysdeps/generic/abort.c: Add libc_hidden_def.
	* stdlib/strtod.c: Likewise.
	* sysdeps/generic/strtol.c: Likewise.
	* sysdeps/wordsize-64/strtol.c: Likewise.
	* sysdeps/wordsize-64/wcstol.c: Likewise.
	* sysdeps/wordsize-64/wcstol_l.c: Likewise.
2002-08-04 01:29:29 +00:00

141 lines
3.7 KiB
C

/* Copyright (C) 1991,93,95,96,97,98,2001,02 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
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <bits/libc-lock.h>
#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>
#ifndef ABORT_INSTRUCTION
/* No such instruction is available. */
# define ABORT_INSTRUCTION
#endif
#ifdef USE_IN_LIBIO
# include <libio/libioP.h>
# define fflush(s) _IO_flush_all_lockp (0)
#endif
/* We must avoid to run in circles. Therefore we remember how far we
already got. */
static int stage;
/* We should be prepared for multiple threads trying to run abort. */
__libc_lock_define_initialized_recursive (static, lock);
/* Cause an abnormal program termination with core-dump. */
void
abort (void)
{
struct sigaction act;
sigset_t sigs;
/* First acquire the lock. */
__libc_lock_lock_recursive (lock);
/* Now it's for sure we are alone. But recursive calls are possible. */
/* Unlock SIGABRT. */
if (stage == 0)
{
++stage;
if (__sigemptyset (&sigs) == 0 &&
__sigaddset (&sigs, SIGABRT) == 0)
__sigprocmask (SIG_UNBLOCK, &sigs, (sigset_t *) NULL);
}
/* Flush all streams. We cannot close them now because the user
might have registered a handler for SIGABRT. */
if (stage == 1)
{
++stage;
fflush (NULL);
}
/* Send signal which possibly calls a user handler. */
if (stage == 2)
{
/* 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 possibility. */
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. */
if (stage == 3)
{
++stage;
memset (&act, '\0', sizeof (struct sigaction));
act.sa_handler = SIG_DFL;
__sigfillset (&act.sa_mask);
act.sa_flags = 0;
__sigaction (SIGABRT, &act, NULL);
}
/* Now close the streams which also flushes the output the user
defined handler might has produced. */
if (stage == 4)
{
++stage;
__fcloseall ();
}
/* Try again. */
if (stage == 5)
{
++stage;
raise (SIGABRT);
}
/* Now try to abort using the system specific command. */
if (stage == 6)
{
++stage;
ABORT_INSTRUCTION;
}
/* If we can't signal ourselves and the abort instruction failed, exit. */
if (stage == 7)
{
++stage;
_exit (127);
}
/* If even this fails try to use the provided instruction to crash
or otherwise make sure we never return. */
while (1)
/* Try for ever and ever. */
ABORT_INSTRUCTION;
}
libc_hidden_def (abort)