1 module mecca.reactor.platform.signals;
2 
3 package(mecca.reactor):
4 
5 version (linux)
6     import signals = mecca.reactor.platform.linux.signals;
7 else version (Darwin)
8     import signals = mecca.reactor.platform.darwin.signals;
9 else
10     static assert("platform not supported");
11 
12 /// ReactorSignal singleton
13 public __gshared signals.ReactorSignal reactorSignal;
14 
15 static if (is(signals.signalfd_siginfo))
16     alias signals.signalfd_siginfo signalfd_siginfo;
17 
18 unittest {
19     import std.process : environment;
20 
21     import mecca.lib.exception : assertGE;
22     import mecca.log : LogToConsole, INFO, WARN;
23     import mecca.reactor : Reactor, theReactor;
24     import mecca.platform.os : OSSignal;
25 
26     if( environment.get("DETERMINSTIC_HINT", "0")=="1" ) {
27         WARN!"Skipping signals test due to environment request"();
28         static if( !LogToConsole ) {
29             import std.stdio: stderr;
30             stderr.writeln( "Skipping signals test due to environment request" );
31         }
32         return;
33     }
34 
35     Reactor.OpenOptions options;
36 
37     // Timing sensitive tests should not suffer GC collection in their middle
38     options.utGcDisabled = true;
39 
40     theReactor.setup(options);
41     scope(success) theReactor.teardown();
42 
43     uint sigcount;
44 
45     void sigHandler(OSSignal) {
46         sigcount++;
47     }
48 
49     void fiberCode() {
50         import core.sys.posix.sys.time;
51         import mecca.lib.exception : errnoCall;
52         import mecca.lib.time;
53         import mecca.platform.os : ITIMER_REAL;
54 
55         reactorSignal.registerHandler(OSSignal.SIGALRM, &sigHandler);
56 
57         itimerval it;
58         it.it_interval.tv_usec = 500; // Wake up every half millisecond. More accurate than our reactor timers ;-)
59         it.it_value = it.it_interval;
60 
61         errnoCall!setitimer(ITIMER_REAL, &it, null);
62 
63         theReactor.sleep(dur!"msecs"(3));
64 
65         // Disarm the timer
66         it.it_value.tv_sec = 0;
67         it.it_value.tv_usec = 0;
68         it.it_interval = it.it_value;
69         errnoCall!setitimer(ITIMER_REAL, &it, null);
70 
71         theReactor.stop();
72     }
73 
74     theReactor.spawnFiber(&fiberCode);
75 
76     theReactor.start();
77 
78     INFO!"500µs timer triggered %s time during 3ms sleep"(sigcount);
79     assertGE(sigcount, 5, "Signal count incorrect"); // Will probably be higher
80 }