aboutsummaryrefslogtreecommitdiffstats
path: root/util/system/interrupt_signals.cpp
blob: 61ff8dd720287f661326274c72d9c8756009392f (plain) (blame)
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
#include "interrupt_signals.h" 
 
#include "compiler.h" 
#include "error.h" 
 
#include <util/generic/yexception.h> 
 
#include <csignal> 
 
static void (*InterruptSignalsHandler)(int signum) = nullptr; 
 
#ifdef _win_ 
 
    #include <windows.h>
 
static BOOL WINAPI WindowsSignalsHandler(_In_ DWORD dwCtrlType) { 
    if (!InterruptSignalsHandler) { 
        return FALSE; 
    } 
 
    switch (dwCtrlType) { 
        case CTRL_C_EVENT: 
            InterruptSignalsHandler(SIGINT); 
            return TRUE; 
        case CTRL_BREAK_EVENT: 
            InterruptSignalsHandler(SIGTERM); 
            return TRUE; 
        case CTRL_CLOSE_EVENT: 
            InterruptSignalsHandler(SIGHUP); 
            return TRUE; 
        default: 
            return FALSE; 
    } 
    Y_UNREACHABLE(); 
} 
 
#endif 
 
// separate function is to enforce 'extern "C"' linkage 
extern "C" void CppSignalsHandler(int signum) { 
    if (InterruptSignalsHandler) { 
        InterruptSignalsHandler(signum); 
    } 
} 
 
void SetInterruptSignalsHandler(void (*handler)(int signum)) { 
    InterruptSignalsHandler = handler; 
#ifdef _win_ 
    if (!SetConsoleCtrlHandler(WindowsSignalsHandler, TRUE)) { 
        ythrow TSystemError() << "SetConsoleCtrlHandler failed: " << LastSystemErrorText(); 
    } 
    for (int signum : {SIGINT, SIGTERM}) { 
#else 
    for (int signum : {SIGINT, SIGTERM, SIGHUP}) { 
#endif 
        if (std::signal(signum, CppSignalsHandler) == SIG_ERR) { 
            ythrow TSystemError() << "std::signal failed to set handler for signal with id " << signum; 
        } 
    } 
}