/* Copyright (C) 1991-2024 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, see
. */
#include
#include
#include
#include
#include
/* Try to get a machine dependent instruction which will make the
program crash. This is used in case everything else fails. */
#include
#ifndef ABORT_INSTRUCTION
/* No such instruction is available. */
# define ABORT_INSTRUCTION
#endif
/* Exported variable to locate abort message in core files etc. */
struct abort_msg_s *__abort_msg;
libc_hidden_def (__abort_msg)
/* The lock is used to prevent multiple thread to change the SIGABRT
to SIG_IGN while abort tries to change to SIG_DFL, and to avoid
a new process to see a wrong disposition if there is a SIGABRT
handler installed. */
__libc_rwlock_define_initialized (static, lock);
void
__abort_fork_reset_child (void)
{
__libc_rwlock_init (lock);
}
void
__abort_lock_rdlock (internal_sigset_t *set)
{
internal_signal_block_all (set);
__libc_rwlock_rdlock (lock);
}
void
__abort_lock_wrlock (internal_sigset_t *set)
{
internal_signal_block_all (set);
__libc_rwlock_wrlock (lock);
}
void
__abort_lock_unlock (const internal_sigset_t *set)
{
__libc_rwlock_unlock (lock);
internal_signal_restore_set (set);
}
/* Cause an abnormal program termination with core-dump. */
_Noreturn void
abort (void)
{
raise (SIGABRT);
/* There is a SIGABRT handle installed and it returned, or SIGABRT was
blocked or ignored. In this case use a AS-safe lock to prevent sigaction
to change the signal disposition again, set the handle to default
disposition, and re-raise the signal. Even if POSIX state this step is
optional, this a QoI by forcing the process termination through the
signal handler. */
__abort_lock_wrlock (NULL);
struct sigaction act = {.sa_handler = SIG_DFL, .sa_flags = 0 };
__sigfillset (&act.sa_mask);
__libc_sigaction (SIGABRT, &act, NULL);
__pthread_raise_internal (SIGABRT);
internal_signal_unblock_signal (SIGABRT);
/* This code should be unreachable, try the arch-specific code and the
syscall fallback. */
ABORT_INSTRUCTION;
_exit (127);
}
libc_hidden_def (abort)