2024-05-11 05:03:12 +00:00
|
|
|
//
|
|
|
|
// signal.cpp
|
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//
|
|
|
|
// signal(), raise(), and related functions
|
|
|
|
//
|
|
|
|
#include <corecrt_internal.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <excpt.h>
|
|
|
|
#include <float.h>
|
|
|
|
#include <malloc.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Variables holding action codes (and code pointers) for SIGINT, SIGBRK,
|
|
|
|
// SIGABRT and SIGTERM.
|
|
|
|
//
|
|
|
|
// note that the disposition (i.e., action to be taken upon receipt) of
|
|
|
|
// these signals is defined on a per-process basis (not per-thread)!!
|
|
|
|
static __crt_state_management::dual_state_global<__crt_signal_handler_t> ctrlc_action; // SIGINT
|
|
|
|
static __crt_state_management::dual_state_global<__crt_signal_handler_t> ctrlbreak_action; // SIGBREAK
|
|
|
|
static __crt_state_management::dual_state_global<__crt_signal_handler_t> abort_action; // SIGABRT
|
|
|
|
static __crt_state_management::dual_state_global<__crt_signal_handler_t> term_action; // SIGTERM
|
|
|
|
|
|
|
|
/*
|
|
|
|
* flag indicated whether or not a handler has been installed to capture
|
|
|
|
* ^C and ^Break events.
|
|
|
|
*/
|
|
|
|
static bool console_ctrl_handler_installed = false;
|
|
|
|
|
|
|
|
#define _SIGHUP_IGNORE 1
|
|
|
|
#define _SIGQUIT_IGNORE 3
|
|
|
|
#define _SIGPIPE_IGNORE 13
|
|
|
|
#define _SIGIOINT_IGNORE 16
|
|
|
|
#define _SIGSTOP_IGNORE 17
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Initializes the signal handler pointers to the encoded nullptr value.
|
|
|
|
extern "C" void __cdecl __acrt_initialize_signal_handlers(void* const encoded_nullptr)
|
|
|
|
{
|
|
|
|
// The encoded nullptr is SIG_DFL
|
|
|
|
ctrlc_action.initialize (reinterpret_cast<__crt_signal_handler_t>(encoded_nullptr));
|
|
|
|
ctrlbreak_action.initialize(reinterpret_cast<__crt_signal_handler_t>(encoded_nullptr));
|
|
|
|
abort_action.initialize (reinterpret_cast<__crt_signal_handler_t>(encoded_nullptr));
|
|
|
|
term_action.initialize (reinterpret_cast<__crt_signal_handler_t>(encoded_nullptr));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Gets the address of the global action for one of the signals that has a
|
|
|
|
// global action. Returns nullptr if the given signal does not have a global
|
|
|
|
// action.
|
|
|
|
static __crt_signal_handler_t* __cdecl get_global_action_nolock(int const signum) throw()
|
|
|
|
{
|
|
|
|
switch (signum)
|
|
|
|
{
|
|
|
|
// CRT_REFACTOR TODO: PERFORMANCE: for OS mode, these might be able to be in the const data section, instead of in writeable page data.
|
|
|
|
case SIGINT: return &ctrlc_action.value();
|
|
|
|
case SIGBREAK: return &ctrlbreak_action.value();
|
|
|
|
case SIGABRT: return &abort_action.value();
|
|
|
|
case SIGABRT_COMPAT: return &abort_action.value();
|
|
|
|
case SIGTERM: return &term_action.value();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Looks up the exception-action table entry for a signal. This function finds
|
|
|
|
// the first entry in the 'action_table' whose _signal_number field is 'signum'.
|
|
|
|
// If no such entry is found, nullptr is returned.
|
|
|
|
static __crt_signal_action_t* __cdecl siglookup(
|
|
|
|
int const signum,
|
|
|
|
__crt_signal_action_t* const action_table
|
|
|
|
) throw()
|
|
|
|
{
|
|
|
|
// Walk through the table looking for the proper entry. Note that in the
|
|
|
|
// case where more than one exception corresponds to the same signal, the
|
|
|
|
// first such instance in the table is the one returned.
|
|
|
|
for (__crt_signal_action_t* p = action_table; p != action_table + __acrt_signal_action_table_count; ++p)
|
|
|
|
if (p->_signal_number == signum)
|
|
|
|
return p;
|
|
|
|
|
|
|
|
// If we reached the end of the table, return nullptr:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Handles failures for signal().
|
|
|
|
static __crt_signal_handler_t __cdecl signal_failed(int const signum) throw()
|
|
|
|
{
|
|
|
|
switch (signum)
|
|
|
|
{
|
|
|
|
case _SIGHUP_IGNORE:
|
|
|
|
case _SIGQUIT_IGNORE:
|
|
|
|
case _SIGPIPE_IGNORE:
|
|
|
|
case _SIGIOINT_IGNORE:
|
|
|
|
case _SIGSTOP_IGNORE:
|
|
|
|
return SIG_ERR;
|
|
|
|
|
|
|
|
default:
|
|
|
|
errno = EINVAL;
|
|
|
|
return SIG_ERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enclaves have no console, thus also no signals specific to consoles.
|
|
|
|
#ifdef _UCRT_ENCLAVE_BUILD
|
|
|
|
|
|
|
|
__inline static BOOL is_unsupported_signal(int const signum, __crt_signal_handler_t const sigact)
|
|
|
|
{
|
|
|
|
return (sigact == SIG_ACK || sigact == SIG_SGE || signum == SIGINT || signum == SIGBREAK);
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline static BOOL is_console_signal(int const)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* ^^^ _UCRT_ENCLAVE_BUILD ^^^ // vvv !_UCRT_ENCLAVE_BUILD vvv */
|
|
|
|
|
|
|
|
__inline static BOOL is_unsupported_signal(int const, __crt_signal_handler_t const sigact)
|
|
|
|
{
|
|
|
|
return (sigact == SIG_ACK || sigact == SIG_SGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline static BOOL is_console_signal(int const signum)
|
|
|
|
{
|
|
|
|
return (signum == SIGINT || signum == SIGBREAK);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* _UCRT_ENCLAVE_BUILD */
|
|
|
|
|
|
|
|
/***
|
|
|
|
*static BOOL WINAPI ctrlevent_capture(DWORD ctrl_type) - capture ^C and ^Break events
|
|
|
|
*
|
|
|
|
*Purpose:
|
|
|
|
* Capture ^C and ^Break events from the console and dispose of them
|
|
|
|
* according the values in ctrlc_action and ctrlbreak_action, resp.
|
|
|
|
* This is the routine that evokes the user-defined action for SIGINT
|
|
|
|
* (^C) or SIGBREAK (^Break) installed by a call to signal().
|
|
|
|
*
|
|
|
|
*Entry:
|
|
|
|
* DWORD ctrl_type - indicates type of event, two values:
|
|
|
|
* CTRL_C_EVENT
|
|
|
|
* CTRL_BREAK_EVENT
|
|
|
|
*
|
|
|
|
*Exit:
|
|
|
|
* Returns TRUE to indicate the event (signal) has been handled.
|
|
|
|
* Otherwise, returns FALSE.
|
|
|
|
*
|
|
|
|
*Exceptions:
|
|
|
|
*
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
static BOOL WINAPI ctrlevent_capture(DWORD const ctrl_type) throw()
|
|
|
|
{
|
|
|
|
__crt_signal_handler_t ctrl_action = nullptr;
|
|
|
|
int signal_code = 0;
|
|
|
|
|
|
|
|
__acrt_lock(__acrt_signal_lock);
|
|
|
|
__try
|
|
|
|
{
|
|
|
|
__crt_signal_handler_t* pctrl_action;
|
|
|
|
|
|
|
|
// Identify the type of event and fetch the corresponding action
|
|
|
|
// description:
|
|
|
|
if (ctrl_type == CTRL_C_EVENT)
|
|
|
|
{
|
|
|
|
pctrl_action = &ctrlc_action.value();
|
|
|
|
ctrl_action = __crt_fast_decode_pointer(*pctrl_action);
|
|
|
|
signal_code = SIGINT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pctrl_action = &ctrlbreak_action.value();
|
|
|
|
ctrl_action = __crt_fast_decode_pointer(*pctrl_action);
|
|
|
|
signal_code = SIGBREAK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctrl_action != SIG_DFL && ctrl_action != SIG_IGN)
|
|
|
|
{
|
|
|
|
// Reset the action to be SIG_DFL:
|
|
|
|
*pctrl_action = __crt_fast_encode_pointer(nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
__finally
|
|
|
|
{
|
|
|
|
__acrt_unlock(__acrt_signal_lock);
|
|
|
|
}
|
2024-10-11 21:05:27 +00:00
|
|
|
__endtry
|
2024-05-11 05:03:12 +00:00
|
|
|
|
|
|
|
// The default signal action leaves the event unhandled, so return false to
|
|
|
|
// indicate such:
|
|
|
|
if (ctrl_action == SIG_DFL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
// If the action is not to ignore the signal, then invoke the action:
|
|
|
|
if (ctrl_action != SIG_IGN)
|
|
|
|
(*ctrl_action)(signal_code);
|
|
|
|
|
|
|
|
// Then return TRUE to indicate the event has been handled (this may mean
|
|
|
|
// that the even is being ignored):
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
*__crt_signal_handler_t signal(signum, sigact) - Define a signal handler
|
|
|
|
*
|
|
|
|
*Purpose:
|
|
|
|
* The signal routine allows the user to define what action should
|
|
|
|
* be taken when various signals occur. The Win32/Dosx32 implementation
|
|
|
|
* supports seven signals, divided up into three general groups
|
|
|
|
*
|
|
|
|
* 1. Signals corresponding to OS exceptions. These are:
|
|
|
|
* SIGFPE
|
|
|
|
* SIGILL
|
|
|
|
* SIGSEGV
|
|
|
|
* Signal actions for these signals are installed by altering the
|
|
|
|
* _action and SigAction fields for the appropriate entry in the
|
|
|
|
* exception-action table (XcptActTab[]).
|
|
|
|
*
|
|
|
|
* 2. Signals corresponding to ^C and ^Break. These are:
|
|
|
|
* SIGINT
|
|
|
|
* SIGBREAK
|
|
|
|
* Signal actions for these signals are installed by altering the
|
|
|
|
* _ctrlc_action and _ctrlbreak_action variables.
|
|
|
|
*
|
|
|
|
* 3. Signals which are implemented only in the runtime. That is, they
|
|
|
|
* occur only as the result of a call to raise().
|
|
|
|
* SIGABRT
|
|
|
|
* SIGTERM
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*Entry:
|
|
|
|
* int signum signal type. recognized signal types are:
|
|
|
|
*
|
|
|
|
* SIGABRT (ANSI)
|
|
|
|
* SIGBREAK
|
|
|
|
* SIGFPE (ANSI)
|
|
|
|
* SIGILL (ANSI)
|
|
|
|
* SIGINT (ANSI)
|
|
|
|
* SIGSEGV (ANSI)
|
|
|
|
* SIGTERM (ANSI)
|
|
|
|
* SIGABRT_COMPAT
|
|
|
|
*
|
|
|
|
* __crt_signal_handler_t sigact signal handling function or action code. the action
|
|
|
|
* codes are:
|
|
|
|
*
|
|
|
|
* SIG_DFL - take the default action, whatever that may
|
|
|
|
* be, upon receipt of this type type of signal.
|
|
|
|
*
|
|
|
|
* SIG_DIE - *** ILLEGAL ***
|
|
|
|
* special code used in the _action field of an
|
|
|
|
* XcptActTab[] entry to indicate that the runtime is
|
|
|
|
* to terminate the process upon receipt of the exception.
|
|
|
|
* not accepted as a value for sigact.
|
|
|
|
*
|
|
|
|
* SIG_IGN - ignore this type of signal
|
|
|
|
*
|
|
|
|
* [function address] - transfer control to this address
|
|
|
|
* when a signal of this type occurs.
|
|
|
|
*
|
|
|
|
*Exit:
|
|
|
|
* Good return:
|
|
|
|
* Signal returns the previous value of the signal handling function
|
|
|
|
* (e.g., SIG_DFL, SIG_IGN, etc., or [function address]). This value is
|
|
|
|
* returned in DX:AX.
|
|
|
|
*
|
|
|
|
* Error return:
|
|
|
|
* Signal returns -1 and errno is set to EINVAL. The error return is
|
|
|
|
* generally taken if the user submits bogus input values.
|
|
|
|
*
|
|
|
|
*Exceptions:
|
|
|
|
* None.
|
|
|
|
*
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
extern "C" __crt_signal_handler_t __cdecl signal(int signum, __crt_signal_handler_t sigact)
|
|
|
|
{
|
|
|
|
// Check for signal actions that are supported on other platforms but not on
|
|
|
|
// this one, and make sure the action is not SIG_DIE:
|
|
|
|
if (is_unsupported_signal(signum, sigact))
|
|
|
|
return signal_failed(signum);
|
|
|
|
|
|
|
|
// First, handle the case where the signal does not correspond to an
|
|
|
|
// exception in the host OS:
|
|
|
|
if (signum == SIGINT ||
|
|
|
|
signum == SIGBREAK ||
|
|
|
|
signum == SIGABRT ||
|
|
|
|
signum == SIGABRT_COMPAT ||
|
|
|
|
signum == SIGTERM)
|
|
|
|
{
|
|
|
|
bool set_console_ctrl_error = false;
|
|
|
|
__crt_signal_handler_t old_action = nullptr;
|
|
|
|
|
|
|
|
__acrt_lock(__acrt_signal_lock);
|
|
|
|
__try
|
|
|
|
{
|
|
|
|
// If the signal is SIGINT or SIGBREAK make sure the handler is
|
|
|
|
// installed to capture ^C and ^Break events:
|
|
|
|
// C4127: conditional expression is constant
|
|
|
|
#pragma warning( suppress: 4127 )
|
|
|
|
if (is_console_signal(signum) && !console_ctrl_handler_installed)
|
|
|
|
{
|
|
|
|
if (SetConsoleCtrlHandler(ctrlevent_capture, TRUE))
|
|
|
|
{
|
|
|
|
console_ctrl_handler_installed = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_doserrno = GetLastError();
|
|
|
|
set_console_ctrl_error = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__crt_signal_handler_t* const action_pointer = get_global_action_nolock(signum);
|
|
|
|
if (action_pointer != nullptr)
|
|
|
|
{
|
|
|
|
old_action = __crt_fast_decode_pointer(*action_pointer);
|
|
|
|
if (sigact != SIG_GET)
|
|
|
|
*action_pointer = __crt_fast_encode_pointer(sigact);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
__finally
|
|
|
|
{
|
|
|
|
__acrt_unlock(__acrt_signal_lock);
|
|
|
|
}
|
2024-10-11 21:05:27 +00:00
|
|
|
__endtry
|
2024-05-11 05:03:12 +00:00
|
|
|
|
|
|
|
if (set_console_ctrl_error)
|
|
|
|
return signal_failed(signum);
|
|
|
|
|
|
|
|
return old_action;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If we reach here, signum is supposed to be one of the signals which
|
|
|
|
// correspond to exceptions on the host OS. If it's not one of these,
|
|
|
|
// fail and return immediately:
|
|
|
|
if (signum != SIGFPE && signum != SIGILL && signum != SIGSEGV)
|
|
|
|
return signal_failed(signum);
|
|
|
|
|
|
|
|
__acrt_ptd* const ptd = __acrt_getptd_noexit();
|
|
|
|
if (ptd == nullptr)
|
|
|
|
return signal_failed(signum);
|
|
|
|
|
|
|
|
// Check that there is a per-thread instance of the exception-action table
|
|
|
|
// for this thread. If there isn't, create one:
|
|
|
|
if (ptd->_pxcptacttab == __acrt_exception_action_table)
|
|
|
|
{
|
|
|
|
// Allocate space for an exception-action table:
|
|
|
|
ptd->_pxcptacttab = static_cast<__crt_signal_action_t*>(_malloc_crt(__acrt_signal_action_table_size));
|
|
|
|
if (ptd->_pxcptacttab == nullptr)
|
|
|
|
return signal_failed(signum);
|
|
|
|
|
|
|
|
// Initialize the table by copying the contents of __acrt_exception_action_table:
|
|
|
|
memcpy(ptd->_pxcptacttab, __acrt_exception_action_table, __acrt_signal_action_table_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look up the proper entry in the exception-action table. Note that if
|
|
|
|
// several exceptions are mapped to the same signal, this returns the
|
|
|
|
// pointer to first such entry in the exception action table. It is assumed
|
|
|
|
// that the other entries immediately follow this one.
|
|
|
|
__crt_signal_action_t* const xcpt_action = siglookup(signum, ptd->_pxcptacttab);
|
|
|
|
if (xcpt_action == nullptr)
|
|
|
|
return signal_failed(signum);
|
|
|
|
|
|
|
|
// SIGSEGV, SIGILL and SIGFPE all have more than one exception mapped to
|
|
|
|
// them. The code below depends on the exceptions corresponding to the same
|
|
|
|
// signal being grouped together in the exception-action table.
|
|
|
|
|
|
|
|
__crt_signal_handler_t const old_action = xcpt_action->_action;
|
|
|
|
|
|
|
|
// If we are not just getting the currently installed action, loop through
|
|
|
|
// all the entries corresponding to the given signal and update them as
|
|
|
|
// appropriate:
|
|
|
|
if (sigact != SIG_GET)
|
|
|
|
{
|
|
|
|
__crt_signal_action_t* const last = ptd->_pxcptacttab + __acrt_signal_action_table_count;
|
|
|
|
|
|
|
|
// Iterate until we reach the end of the table or we reach the end of
|
|
|
|
// the range of actions for this signal, whichever comes first:
|
|
|
|
for (__crt_signal_action_t* p = xcpt_action; p != last && p->_signal_number == signum; ++p)
|
|
|
|
{
|
|
|
|
p->_action = sigact;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return old_action;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***
|
|
|
|
*int raise(signum) - Raise a signal
|
|
|
|
*
|
|
|
|
*Purpose:
|
|
|
|
* This routine raises a signal (i.e., performs the action currently
|
|
|
|
* defined for this signal). The action associated with the signal is
|
|
|
|
* evoked directly without going through intermediate dispatching or
|
|
|
|
* handling.
|
|
|
|
*
|
|
|
|
*Entry:
|
|
|
|
* int signum - signal type (e.g., SIGINT)
|
|
|
|
*
|
|
|
|
*Exit:
|
|
|
|
* returns 0 on good return, -1 on bad return.
|
|
|
|
*
|
|
|
|
*Exceptions:
|
|
|
|
* May not return. Raise has no control over the action
|
|
|
|
* routines defined for the various signals. Those routines may
|
|
|
|
* abort, terminate, etc. In particular, the default actions for
|
|
|
|
* certain signals will terminate the program.
|
|
|
|
*
|
|
|
|
*******************************************************************************/
|
|
|
|
extern "C" int __cdecl raise(int const signum)
|
|
|
|
{
|
|
|
|
__acrt_ptd* ptd = nullptr;
|
|
|
|
int old_fpecode = 0;
|
|
|
|
|
|
|
|
__crt_signal_handler_t* action_pointer = nullptr;
|
|
|
|
bool action_is_global = true;
|
|
|
|
switch (signum)
|
|
|
|
{
|
|
|
|
case SIGINT:
|
|
|
|
case SIGBREAK:
|
|
|
|
case SIGABRT:
|
|
|
|
case SIGABRT_COMPAT:
|
|
|
|
case SIGTERM:
|
|
|
|
action_pointer = get_global_action_nolock(signum);;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGFPE:
|
|
|
|
case SIGILL:
|
|
|
|
case SIGSEGV:
|
|
|
|
{
|
|
|
|
ptd = __acrt_getptd_noexit();
|
|
|
|
if (ptd == nullptr)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
__crt_signal_action_t* const local_action = siglookup(signum, ptd->_pxcptacttab);
|
|
|
|
_VALIDATE_RETURN(local_action != nullptr, EINVAL, -1);
|
|
|
|
action_pointer = &local_action->_action;
|
|
|
|
action_is_global = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// unsupported signal, return an error
|
|
|
|
_VALIDATE_RETURN(("Invalid signal or error", 0), EINVAL, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PEXCEPTION_POINTERS old_pxcptinfoptrs = nullptr;
|
|
|
|
|
|
|
|
// If the action is global, we must acquire the lock before accessing it:
|
|
|
|
if (action_is_global)
|
|
|
|
__acrt_lock(__acrt_signal_lock);
|
|
|
|
|
|
|
|
__crt_signal_handler_t action = nullptr;
|
|
|
|
bool return0 = false;
|
|
|
|
__try
|
|
|
|
{
|
|
|
|
// Global function pointers are encoded; per-thread pointers are not:
|
|
|
|
action = action_is_global ? __crt_fast_decode_pointer(*action_pointer) : *action_pointer;
|
|
|
|
|
|
|
|
// If the current action is SIG_IGN, just return:
|
|
|
|
return0 = action == SIG_IGN;
|
|
|
|
if (return0)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// If the current action is SIG_DFL, take the default action. The current
|
|
|
|
// default action for all of the supported signals is to terminate with an
|
|
|
|
// exit code of 3:
|
|
|
|
if (action == SIG_DFL)
|
|
|
|
{
|
|
|
|
// Be sure to unlock before entering the exit code. The exit function
|
|
|
|
// does not return.
|
|
|
|
if (action_is_global)
|
|
|
|
__acrt_unlock(__acrt_signal_lock);
|
|
|
|
|
|
|
|
_exit(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
// For signals that correspond to exceptions, set the pointer to the
|
|
|
|
// EXCEPTION_POINTERS structure to nullptr:
|
|
|
|
if (signum == SIGFPE || signum == SIGSEGV || signum == SIGILL)
|
|
|
|
{
|
|
|
|
old_pxcptinfoptrs = ptd->_tpxcptinfoptrs;
|
|
|
|
ptd->_tpxcptinfoptrs = nullptr;
|
|
|
|
|
|
|
|
// If the signal is SIGFPE, also set _fpecode to _FPE_EXPLICITGEN:
|
|
|
|
if ( signum == SIGFPE )
|
|
|
|
{
|
|
|
|
old_fpecode = _fpecode;
|
|
|
|
_fpecode = _FPE_EXPLICITGEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset the action to SIG_DFL before calling the user-specified handler.
|
|
|
|
// For SIGFPE, we must reset the action for all of the FP exceptions:
|
|
|
|
if (signum == SIGFPE)
|
|
|
|
{
|
|
|
|
__crt_signal_action_t* const first = ptd->_pxcptacttab + __acrt_signal_action_first_fpe_index;
|
|
|
|
__crt_signal_action_t* const last = first + __acrt_signal_action_fpe_count;
|
|
|
|
|
|
|
|
for (__crt_signal_action_t* p = first; p != last; ++p)
|
|
|
|
{
|
|
|
|
p->_action = SIG_DFL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*action_pointer = __crt_fast_encode_pointer(nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
__finally
|
|
|
|
{
|
|
|
|
if (action_is_global)
|
|
|
|
__acrt_unlock(__acrt_signal_lock);
|
|
|
|
}
|
2024-10-11 21:05:27 +00:00
|
|
|
__endtry
|
2024-05-11 05:03:12 +00:00
|
|
|
|
|
|
|
if (return0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Call the user-specified handler routine. For SIGFPE, we have special
|
|
|
|
// code to support old handlers which expect the value of _fpecode as the
|
|
|
|
// second argument:
|
|
|
|
if (signum == SIGFPE)
|
|
|
|
{
|
|
|
|
reinterpret_cast<void(__cdecl*)(int,int)>(action)(SIGFPE, _fpecode);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
action(signum);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// For signals that correspond to exceptions, restore the pointer to the
|
|
|
|
// EXCEPTION_POINTERS structure:
|
|
|
|
if (signum == SIGFPE || signum == SIGSEGV || signum == SIGILL)
|
|
|
|
{
|
|
|
|
ptd->_tpxcptinfoptrs = old_pxcptinfoptrs;
|
|
|
|
|
|
|
|
// If signum is SIGFPE, also restore _fpecode
|
|
|
|
if (signum == SIGFPE)
|
|
|
|
_fpecode = old_fpecode;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Gets the SIGABRT signal handling function
|
|
|
|
extern "C" __crt_signal_handler_t __cdecl __acrt_get_sigabrt_handler()
|
|
|
|
{
|
|
|
|
return __acrt_lock_and_call(__acrt_signal_lock, []
|
|
|
|
{
|
|
|
|
return __crt_fast_decode_pointer(abort_action.value());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the FPE code for the current thread
|
|
|
|
extern "C" int* __cdecl __fpecode()
|
|
|
|
{
|
|
|
|
return &__acrt_getptd()->_tfpecode;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a pointer to the signal handlers for the current thread
|
|
|
|
extern "C" void** __cdecl __pxcptinfoptrs()
|
|
|
|
{
|
|
|
|
return reinterpret_cast<void**>(&__acrt_getptd()->_tpxcptinfoptrs);
|
|
|
|
}
|