ReactOS 0.4.16-dev-889-g9563c07
signal.cpp File Reference
#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>
Include dependency graph for signal.cpp:

Go to the source code of this file.

Macros

#define _SIGHUP_IGNORE   1
 
#define _SIGQUIT_IGNORE   3
 
#define _SIGPIPE_IGNORE   13
 
#define _SIGIOINT_IGNORE   16
 
#define _SIGSTOP_IGNORE   17
 

Functions

void __cdecl __acrt_initialize_signal_handlers (void *const encoded_nullptr)
 
static __crt_signal_handler_t *__cdecl get_global_action_nolock (int const signum) throw ()
 
static __crt_signal_action_t *__cdecl siglookup (int const signum, __crt_signal_action_t *const action_table) throw ()
 
static __crt_signal_handler_t __cdecl signal_failed (int const signum) throw ()
 
static __inline BOOL is_unsupported_signal (int const, __crt_signal_handler_t const sigact)
 
static __inline BOOL is_console_signal (int const signum)
 
static BOOL WINAPI ctrlevent_capture (DWORD const ctrl_type) throw ()
 
__crt_signal_handler_t __cdecl signal (int signum, __crt_signal_handler_t sigact)
 
int __cdecl raise (int const signum)
 
__crt_signal_handler_t __cdecl __acrt_get_sigabrt_handler ()
 
int *__cdecl __fpecode ()
 
void **__cdecl __pxcptinfoptrs ()
 

Variables

static __crt_state_management::dual_state_global< __crt_signal_handler_tctrlc_action
 
static __crt_state_management::dual_state_global< __crt_signal_handler_tctrlbreak_action
 
static __crt_state_management::dual_state_global< __crt_signal_handler_tabort_action
 
static __crt_state_management::dual_state_global< __crt_signal_handler_tterm_action
 
static bool console_ctrl_handler_installed = false
 

Macro Definition Documentation

◆ _SIGHUP_IGNORE

#define _SIGHUP_IGNORE   1

Definition at line 35 of file signal.cpp.

◆ _SIGIOINT_IGNORE

#define _SIGIOINT_IGNORE   16

Definition at line 38 of file signal.cpp.

◆ _SIGPIPE_IGNORE

#define _SIGPIPE_IGNORE   13

Definition at line 37 of file signal.cpp.

◆ _SIGQUIT_IGNORE

#define _SIGQUIT_IGNORE   3

Definition at line 36 of file signal.cpp.

◆ _SIGSTOP_IGNORE

#define _SIGSTOP_IGNORE   17

Definition at line 39 of file signal.cpp.

Function Documentation

◆ __acrt_get_sigabrt_handler()

__crt_signal_handler_t __cdecl __acrt_get_sigabrt_handler ( void  )

Definition at line 564 of file signal.cpp.

565{
566 return __acrt_lock_and_call(__acrt_signal_lock, []
567 {
568 return __crt_fast_decode_pointer(abort_action.value());
569 });
570}
@ __acrt_signal_lock
static __crt_state_management::dual_state_global< __crt_signal_handler_t > abort_action
Definition: signal.cpp:26

Referenced by abort(), and common_message_window().

◆ __acrt_initialize_signal_handlers()

void __cdecl __acrt_initialize_signal_handlers ( void *const  encoded_nullptr)

Definition at line 44 of file signal.cpp.

45{
46 // The encoded nullptr is SIG_DFL
47 ctrlc_action.initialize (reinterpret_cast<__crt_signal_handler_t>(encoded_nullptr));
48 ctrlbreak_action.initialize(reinterpret_cast<__crt_signal_handler_t>(encoded_nullptr));
49 abort_action.initialize (reinterpret_cast<__crt_signal_handler_t>(encoded_nullptr));
50 term_action.initialize (reinterpret_cast<__crt_signal_handler_t>(encoded_nullptr));
51}
void(__cdecl * __crt_signal_handler_t)(int)
static __crt_state_management::dual_state_global< __crt_signal_handler_t > term_action
Definition: signal.cpp:27
static __crt_state_management::dual_state_global< __crt_signal_handler_t > ctrlbreak_action
Definition: signal.cpp:25
static __crt_state_management::dual_state_global< __crt_signal_handler_t > ctrlc_action
Definition: signal.cpp:24

◆ __fpecode()

int *__cdecl __fpecode ( void  )

Definition at line 573 of file signal.cpp.

574{
575 return &__acrt_getptd()->_tfpecode;
576}
__acrt_ptd *__cdecl __acrt_getptd(void)

◆ __pxcptinfoptrs()

void **__cdecl __pxcptinfoptrs ( void  )

Definition at line 579 of file signal.cpp.

580{
581 return reinterpret_cast<void**>(&__acrt_getptd()->_tpxcptinfoptrs);
582}
EXCEPTION_POINTERS * _tpxcptinfoptrs

Referenced by sighandler(), and test___pxcptinfoptrs().

◆ ctrlevent_capture()

static BOOL WINAPI ctrlevent_capture ( DWORD const  ctrl_type)
throw (
)
static

Definition at line 163 of file signal.cpp.

164{
165 __crt_signal_handler_t ctrl_action = nullptr;
166 int signal_code = 0;
167
169 __try
170 {
171 __crt_signal_handler_t* pctrl_action;
172
173 // Identify the type of event and fetch the corresponding action
174 // description:
175 if (ctrl_type == CTRL_C_EVENT)
176 {
177 pctrl_action = &ctrlc_action.value();
178 ctrl_action = __crt_fast_decode_pointer(*pctrl_action);
179 signal_code = SIGINT;
180 }
181 else
182 {
183 pctrl_action = &ctrlbreak_action.value();
184 ctrl_action = __crt_fast_decode_pointer(*pctrl_action);
185 signal_code = SIGBREAK;
186 }
187
188 if (ctrl_action != SIG_DFL && ctrl_action != SIG_IGN)
189 {
190 // Reset the action to be SIG_DFL:
191 *pctrl_action = __crt_fast_encode_pointer(nullptr);
192 }
193 }
195 {
197 }
199
200 // The default signal action leaves the event unhandled, so return false to
201 // indicate such:
202 if (ctrl_action == SIG_DFL)
203 return FALSE;
204
205 // If the action is not to ignore the signal, then invoke the action:
206 if (ctrl_action != SIG_IGN)
207 (*ctrl_action)(signal_code);
208
209 // Then return TRUE to indicate the event has been handled (this may mean
210 // that the even is being ignored):
211 return TRUE;
212}
void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock)
Definition: locks.cpp:57
#define SIG_DFL
Definition: signal.h:47
#define SIGINT
Definition: signal.h:23
#define SIG_IGN
Definition: signal.h:48
#define SIGBREAK
Definition: signal.h:40
__acrt_lock(__acrt_heap_lock)
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define __try
Definition: pseh2_64.h:188
#define __endtry
Definition: pseh2_64.h:191
#define __finally
Definition: pseh2_64.h:190
#define CTRL_C_EVENT
Definition: wincon.h:68

Referenced by signal().

◆ get_global_action_nolock()

static __crt_signal_handler_t *__cdecl get_global_action_nolock ( int const  signum)
throw (
)
static

Definition at line 58 of file signal.cpp.

59{
60 switch (signum)
61 {
62 // CRT_REFACTOR TODO: PERFORMANCE: for OS mode, these might be able to be in the const data section, instead of in writeable page data.
63 case SIGINT: return &ctrlc_action.value();
64 case SIGBREAK: return &ctrlbreak_action.value();
65 case SIGABRT: return &abort_action.value();
66 case SIGABRT_COMPAT: return &abort_action.value();
67 case SIGTERM: return &term_action.value();
68 }
69
70 return nullptr;
71}
#define SIGABRT_COMPAT
Definition: signal.h:43
#define SIGTERM
Definition: signal.h:39
#define SIGABRT
Definition: signal.h:28

Referenced by raise(), and signal().

◆ is_console_signal()

static __inline BOOL is_console_signal ( int const  signum)
static

Definition at line 134 of file signal.cpp.

135{
136 return (signum == SIGINT || signum == SIGBREAK);
137}

Referenced by signal().

◆ is_unsupported_signal()

static __inline BOOL is_unsupported_signal ( int const  ,
__crt_signal_handler_t const  sigact 
)
static

Definition at line 129 of file signal.cpp.

130{
131 return (sigact == SIG_ACK || sigact == SIG_SGE);
132}
#define SIG_SGE
Definition: signal.h:50
#define SIG_ACK
Definition: signal.h:51

Referenced by signal().

◆ raise()

int __cdecl raise ( int const  signum)

Definition at line 425 of file signal.cpp.

426{
427 __acrt_ptd* ptd = nullptr;
428 int old_fpecode = 0;
429
430 __crt_signal_handler_t* action_pointer = nullptr;
431 bool action_is_global = true;
432 switch (signum)
433 {
434 case SIGINT:
435 case SIGBREAK:
436 case SIGABRT:
437 case SIGABRT_COMPAT:
438 case SIGTERM:
439 action_pointer = get_global_action_nolock(signum);;
440 break;
441
442 case SIGFPE:
443 case SIGILL:
444 case SIGSEGV:
445 {
447 if (ptd == nullptr)
448 return -1;
449
450 __crt_signal_action_t* const local_action = siglookup(signum, ptd->_pxcptacttab);
451 _VALIDATE_RETURN(local_action != nullptr, EINVAL, -1);
452 action_pointer = &local_action->_action;
453 action_is_global = false;
454 break;
455 }
456 default:
457 // unsupported signal, return an error
458 _VALIDATE_RETURN(("Invalid signal or error", 0), EINVAL, -1);
459 }
460
461
462 PEXCEPTION_POINTERS old_pxcptinfoptrs = nullptr;
463
464 // If the action is global, we must acquire the lock before accessing it:
465 if (action_is_global)
467
469 bool return0 = false;
470 __try
471 {
472 // Global function pointers are encoded; per-thread pointers are not:
473 action = action_is_global ? __crt_fast_decode_pointer(*action_pointer) : *action_pointer;
474
475 // If the current action is SIG_IGN, just return:
476 return0 = action == SIG_IGN;
477 if (return0)
478 __leave;
479
480 // If the current action is SIG_DFL, take the default action. The current
481 // default action for all of the supported signals is to terminate with an
482 // exit code of 3:
483 if (action == SIG_DFL)
484 {
485 // Be sure to unlock before entering the exit code. The exit function
486 // does not return.
487 if (action_is_global)
489
490 _exit(3);
491 }
492
493 // For signals that correspond to exceptions, set the pointer to the
494 // EXCEPTION_POINTERS structure to nullptr:
495 if (signum == SIGFPE || signum == SIGSEGV || signum == SIGILL)
496 {
497 old_pxcptinfoptrs = ptd->_tpxcptinfoptrs;
498 ptd->_tpxcptinfoptrs = nullptr;
499
500 // If the signal is SIGFPE, also set _fpecode to _FPE_EXPLICITGEN:
501 if ( signum == SIGFPE )
502 {
503 old_fpecode = _fpecode;
505 }
506 }
507
508 // Reset the action to SIG_DFL before calling the user-specified handler.
509 // For SIGFPE, we must reset the action for all of the FP exceptions:
510 if (signum == SIGFPE)
511 {
514
515 for (__crt_signal_action_t* p = first; p != last; ++p)
516 {
517 p->_action = SIG_DFL;
518 }
519 }
520 else
521 {
522 *action_pointer = __crt_fast_encode_pointer(nullptr);
523 }
524 }
526 {
527 if (action_is_global)
529 }
531
532 if (return0)
533 return 0;
534
535 // Call the user-specified handler routine. For SIGFPE, we have special
536 // code to support old handlers which expect the value of _fpecode as the
537 // second argument:
538 if (signum == SIGFPE)
539 {
540 reinterpret_cast<void(__cdecl*)(int,int)>(action)(SIGFPE, _fpecode);
541 }
542 else
543 {
544 action(signum);
545 }
546
547
548 // For signals that correspond to exceptions, restore the pointer to the
549 // EXCEPTION_POINTERS structure:
550 if (signum == SIGFPE || signum == SIGSEGV || signum == SIGILL)
551 {
552 ptd->_tpxcptinfoptrs = old_pxcptinfoptrs;
553
554 // If signum is SIGFPE, also restore _fpecode
555 if (signum == SIGFPE)
556 _fpecode = old_fpecode;
557 }
558
559 return 0;
560}
void _exit(int exitcode)
Definition: _exit.c:25
#define EINVAL
Definition: acclib.h:90
#define __cdecl
Definition: accygwin.h:79
size_t const __acrt_signal_action_first_fpe_index
size_t const __acrt_signal_action_fpe_count
__acrt_ptd *__cdecl __acrt_getptd_noexit(void)
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
#define SIGILL
Definition: signal.h:25
#define SIGFPE
Definition: signal.h:30
#define SIGSEGV
Definition: signal.h:33
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
const WCHAR * action
Definition: action.c:7509
const GLint * first
Definition: glext.h:5794
GLfloat GLfloat p
Definition: glext.h:8902
#define _FPE_EXPLICITGEN
Definition: float.h:109
#define _fpecode
Definition: float.h:157
static UINT UINT last
Definition: font.c:45
#define __leave
Definition: pseh2_64.h:192
static __crt_signal_action_t *__cdecl siglookup(int const signum, __crt_signal_action_t *const action_table)
Definition: signal.cpp:78
static __crt_signal_handler_t *__cdecl get_global_action_nolock(int const signum)
Definition: signal.cpp:58
__crt_signal_handler_t _action

Referenced by _CrtHandleDbgReport(), abort(), common_assert_to_message_box(), common_message_window(), getline(), test___pxcptinfoptrs(), and test_signal().

◆ siglookup()

static __crt_signal_action_t *__cdecl siglookup ( int const  signum,
__crt_signal_action_t *const  action_table 
)
throw (
)
static

Definition at line 78 of file signal.cpp.

82{
83 // Walk through the table looking for the proper entry. Note that in the
84 // case where more than one exception corresponds to the same signal, the
85 // first such instance in the table is the one returned.
86 for (__crt_signal_action_t* p = action_table; p != action_table + __acrt_signal_action_table_count; ++p)
87 if (p->_signal_number == signum)
88 return p;
89
90 // If we reached the end of the table, return nullptr:
91 return nullptr;
92}
size_t const __acrt_signal_action_table_count

Referenced by raise(), and signal().

◆ signal()

__crt_signal_handler_t __cdecl signal ( int  signum,
__crt_signal_handler_t  sigact 
)

Definition at line 287 of file signal.cpp.

288{
289 // Check for signal actions that are supported on other platforms but not on
290 // this one, and make sure the action is not SIG_DIE:
291 if (is_unsupported_signal(signum, sigact))
292 return signal_failed(signum);
293
294 // First, handle the case where the signal does not correspond to an
295 // exception in the host OS:
296 if (signum == SIGINT ||
297 signum == SIGBREAK ||
298 signum == SIGABRT ||
299 signum == SIGABRT_COMPAT ||
300 signum == SIGTERM)
301 {
302 bool set_console_ctrl_error = false;
303 __crt_signal_handler_t old_action = nullptr;
304
306 __try
307 {
308 // If the signal is SIGINT or SIGBREAK make sure the handler is
309 // installed to capture ^C and ^Break events:
310 // C4127: conditional expression is constant
311#pragma warning( suppress: 4127 )
313 {
315 {
317 }
318 else
319 {
321 set_console_ctrl_error = true;
322 }
323 }
324
325 __crt_signal_handler_t* const action_pointer = get_global_action_nolock(signum);
326 if (action_pointer != nullptr)
327 {
328 old_action = __crt_fast_decode_pointer(*action_pointer);
329 if (sigact != SIG_GET)
330 *action_pointer = __crt_fast_encode_pointer(sigact);
331 }
332 }
334 {
336 }
338
339 if (set_console_ctrl_error)
340 return signal_failed(signum);
341
342 return old_action;
343 }
344
345
346 // If we reach here, signum is supposed to be one of the signals which
347 // correspond to exceptions on the host OS. If it's not one of these,
348 // fail and return immediately:
349 if (signum != SIGFPE && signum != SIGILL && signum != SIGSEGV)
350 return signal_failed(signum);
351
353 if (ptd == nullptr)
354 return signal_failed(signum);
355
356 // Check that there is a per-thread instance of the exception-action table
357 // for this thread. If there isn't, create one:
358 if (ptd->_pxcptacttab == __acrt_exception_action_table)
359 {
360 // Allocate space for an exception-action table:
362 if (ptd->_pxcptacttab == nullptr)
363 return signal_failed(signum);
364
365 // Initialize the table by copying the contents of __acrt_exception_action_table:
367 }
368
369 // Look up the proper entry in the exception-action table. Note that if
370 // several exceptions are mapped to the same signal, this returns the
371 // pointer to first such entry in the exception action table. It is assumed
372 // that the other entries immediately follow this one.
373 __crt_signal_action_t* const xcpt_action = siglookup(signum, ptd->_pxcptacttab);
374 if (xcpt_action == nullptr)
375 return signal_failed(signum);
376
377 // SIGSEGV, SIGILL and SIGFPE all have more than one exception mapped to
378 // them. The code below depends on the exceptions corresponding to the same
379 // signal being grouped together in the exception-action table.
380
381 __crt_signal_handler_t const old_action = xcpt_action->_action;
382
383 // If we are not just getting the currently installed action, loop through
384 // all the entries corresponding to the given signal and update them as
385 // appropriate:
386 if (sigact != SIG_GET)
387 {
389
390 // Iterate until we reach the end of the table or we reach the end of
391 // the range of actions for this signal, whichever comes first:
392 for (__crt_signal_action_t* p = xcpt_action; p != last && p->_signal_number == signum; ++p)
393 {
394 p->_action = sigact;
395 }
396 }
397
398 return old_action;
399}
struct __crt_signal_action_t const __acrt_exception_action_table[]
size_t const __acrt_signal_action_table_size
#define SIG_GET
Definition: signal.h:49
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2109
#define _doserrno
Definition: stdlib.h:131
#define _malloc_crt
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static bool console_ctrl_handler_installed
Definition: signal.cpp:33
static __crt_signal_handler_t __cdecl signal_failed(int const signum)
Definition: signal.cpp:97
static __inline BOOL is_unsupported_signal(int const, __crt_signal_handler_t const sigact)
Definition: signal.cpp:129
static BOOL WINAPI ctrlevent_capture(DWORD const ctrl_type)
Definition: signal.cpp:163
static __inline BOOL is_console_signal(int const signum)
Definition: signal.cpp:134
DWORD WINAPI GetLastError(void)
Definition: except.c:1042

◆ signal_failed()

static __crt_signal_handler_t __cdecl signal_failed ( int const  signum)
throw (
)
static

Definition at line 97 of file signal.cpp.

98{
99 switch (signum)
100 {
101 case _SIGHUP_IGNORE:
102 case _SIGQUIT_IGNORE:
103 case _SIGPIPE_IGNORE:
104 case _SIGIOINT_IGNORE:
105 case _SIGSTOP_IGNORE:
106 return SIG_ERR;
107
108 default:
109 errno = EINVAL;
110 return SIG_ERR;
111 }
112}
#define SIG_ERR
Definition: signal.h:52
#define errno
Definition: errno.h:18
#define _SIGQUIT_IGNORE
Definition: signal.cpp:36
#define _SIGSTOP_IGNORE
Definition: signal.cpp:39
#define _SIGHUP_IGNORE
Definition: signal.cpp:35
#define _SIGIOINT_IGNORE
Definition: signal.cpp:38
#define _SIGPIPE_IGNORE
Definition: signal.cpp:37

Referenced by signal().

Variable Documentation

◆ abort_action

__crt_state_management::dual_state_global<__crt_signal_handler_t> abort_action
static

◆ console_ctrl_handler_installed

bool console_ctrl_handler_installed = false
static

Definition at line 33 of file signal.cpp.

Referenced by signal().

◆ ctrlbreak_action

__crt_state_management::dual_state_global<__crt_signal_handler_t> ctrlbreak_action
static

◆ ctrlc_action

__crt_state_management::dual_state_global<__crt_signal_handler_t> ctrlc_action
static

◆ term_action

__crt_state_management::dual_state_global<__crt_signal_handler_t> term_action
static

Definition at line 27 of file signal.cpp.

Referenced by __acrt_initialize_signal_handlers(), and get_global_action_nolock().