1 /++
2     Signal handling
3  +/
4 module socketplate.signal;
5 
6 import core.thread : Thread;
7 import socketplate.log;
8 import std.string : format;
9 
10 alias SignalFunc = void delegate(int) nothrow @nogc;
11 
12 ///
13 void setupSignalHandlers(SignalFunc handler) @safe
14 in (handler !is null)
15 {
16     logTrace(format!"Setting up signal handlers for thread: 0x%X"(Thread.getThis().id));
17     _onSignal = handler;
18 
19     version (Posix)
20     {
21         import core.sys.posix.signal;
22 
23         () @trusted {
24             signal(SIGINT, &_socketplate_posix_signal_handler);
25             signal(SIGTERM, &_socketplate_posix_signal_handler);
26         }();
27     }
28     else
29     {
30         version (Windows)
31         {
32             // TODO
33             // SetConsoleCtrlHandler(…);
34             logError("ConsoleCtrlHandler not implemented yet");
35         }
36         else
37         {
38             logError(
39                 "Signal handlers either not available on or implemented for this platform."
40             );
41         }
42     }
43 }
44 
45 ///
46 void forwardSignal(int signal, Thread[] threads) @safe nothrow @nogc
47 {
48     foreach (thread; threads)
49         forwardSignal(signal, thread);
50 }
51 
52 ///
53 void forwardSignal(int signal, Thread thread) @safe nothrow @nogc
54 {
55     version (Posix)
56     {
57         import core.sys.posix.pthread;
58 
59         immutable bool isRunning = () @trusted { return thread.isRunning(); }();
60         if (!isRunning)
61             return;
62 
63         pthread_t threadID;
64         try
65             threadID = thread.id;
66         catch (Exception)
67             return;
68 
69         () @trusted { pthread_kill(threadID, signal); }();
70     }
71     else
72     {
73         logError("Signal forwarding not implemented on this platform");
74     }
75 }
76 
77 private
78 {
79     version (Posix)
80     {
81         // thread local signal handler
82         static SignalFunc _onSignal = null;
83 
84         extern (C) void _socketplate_posix_signal_handler(int signal) nothrow @nogc
85         {
86             if (_onSignal is null)
87                 return;
88 
89             return _onSignal(signal);
90         }
91     }
92 }