-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSigWait.cpp
More file actions
107 lines (84 loc) · 3.09 KB
/
SigWait.cpp
File metadata and controls
107 lines (84 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/** ======================================================================+
+ Copyright @2020-2022 Arjun Ray
+ Released under MIT License
+ see https://mit-license.org
+========================================================================*/
#include "utility/SigWait.h"
#include "utility/StackTrace.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
namespace
{
void sigsegv_handler( int, siginfo_t*, void* ) { throw Utility::TrapException("SIGSEGV at:\n"); }
void sigbus_handler( int, siginfo_t*, void* ) { throw Utility::TrapException("SIGBUS at:\n"); }
void sigfpe_handler( int, siginfo_t*, void* ) { throw Utility::TrapException("SIGFPE at:\n"); }
void sigill_handler( int, siginfo_t*, void* ) { throw Utility::TrapException("SIGILL at:\n"); }
void do_nothing( void*, pid_t, int ) {}
Utility::SigChldCallback sccb = do_nothing; // default setting
void* cbarg = nullptr;
void sigchld_handler( int, siginfo_t*, void* )
{
pid_t _pid;
int _status;
while ( (_pid = ::waitpid( -1, &_status, WNOHANG )) > 0 ) { (*sccb)( cbarg, _pid, _status ); }
}
} // anonymous namespace
namespace Utility
{
SigMask::SigMask()
{
::sigemptyset( &mask_ );
::sigaddset( &mask_, SIGINT );
::sigaddset( &mask_, SIGTERM );
::sigaddset( &mask_, SIGHUP );
::sigaddset( &mask_, SIGQUIT );
::sigaddset( &mask_, SIGCONT );
pthread_sigmask( SIG_BLOCK, &mask_, nullptr );
}
/* static */
void SigWait::install_handlers( bool childAlso )
{
struct sigaction _action;
::sigemptyset( &_action.sa_mask );
_action.sa_flags = 0;
// convert SIGPIPE to inband EPIPE error
_action.sa_handler = SIG_IGN;
::sigaction( SIGPIPE, &_action, nullptr );
// convert traps to exceptions
_action.sa_flags = SA_SIGINFO;
_action.sa_sigaction = sigsegv_handler;
::sigaction( SIGSEGV, &_action, nullptr );
_action.sa_sigaction = sigbus_handler;
::sigaction( SIGBUS, &_action, nullptr );
_action.sa_sigaction = sigfpe_handler;
::sigaction( SIGFPE, &_action, nullptr );
_action.sa_sigaction = sigill_handler;
::sigaction( SIGILL, &_action, nullptr );
if ( childAlso )
{
_action.sa_sigaction = sigchld_handler;
::sigaction( SIGCHLD, &_action, nullptr );
}
}
/* static */
void SigWait::set_sigchld_cb( SigChldCallback cb, void* arg )
{
sccb = cb == nullptr ? do_nothing : cb;
cbarg = cb == nullptr ? nullptr : arg;
}
/* static */
void SigWait::ignore_children()
{
struct sigaction _action;
::sigemptyset( &_action.sa_mask );
_action.sa_flags = SA_NOCLDWAIT | SA_NOCLDSTOP;
_action.sa_handler = SIG_IGN;
::sigaction( SIGCHLD, &_action, nullptr );
}
/* static */
void SigWait::die( bool crash )
{
::kill( ::getpid(), crash ? SIGABRT : SIGTERM );
}
} // namespace Utility