1 module concurrency.signal; 2 3 struct SignalHandler { 4 private __gshared void delegate(int) callback = null; 5 private void delegate(int) oldCallback; 6 extern (C) static void intr(int i) nothrow @nogc { 7 if (callback is null) 8 return; 9 // TODO: this cast is a bit sketchy 10 (cast(void delegate(int) nothrow @nogc) callback)(i); 11 } 12 13 version (Posix) { 14 import core.sys.posix.signal; 15 private sigaction_t[int] previous; 16 } else version (Windows) { 17 alias Fun = extern (C) void function(int) nothrow @nogc @system; 18 private Fun[int] previous; 19 } else static assert("Platform not supported"); 20 21 void setup(void delegate(int) cb) @trusted { 22 oldCallback = callback; 23 callback = cb; 24 } 25 26 void on(int s) @trusted { 27 version (Posix) { 28 import core.sys.posix.signal; 29 30 sigaction_t old; 31 sigset_t sigset; 32 sigemptyset(&sigset); 33 sigaction_t siginfo; 34 siginfo.sa_handler = &intr; 35 siginfo.sa_mask = sigset; 36 siginfo.sa_flags = SA_RESTART; 37 sigaction(s, &siginfo, &old); 38 } else { 39 import core.stdc.signal; 40 Fun old = signal(s, &intr); 41 } 42 previous[s] = old; 43 } 44 45 void forward(int sig) @trusted { 46 foreach(s, old; previous) { 47 if (s != sig) 48 continue; 49 version (Posix) { 50 if (old.sa_handler) 51 old.sa_handler(s); 52 } 53 else if (old) 54 old(s); 55 } 56 } 57 58 void teardown() nothrow @trusted { 59 callback = oldCallback; 60 try { 61 foreach(s, old; previous) { 62 version (Posix) { 63 sigaction(s, &old, null); 64 } else { 65 import core.stdc.signal; 66 signal(s, old); 67 } 68 } 69 } catch (Exception e) {} 70 } 71 }