1() = evalfile ("inc.sl");
2
3testing_feature ("signals\n");
4
5private variable Signal = 0;
6
7private define handle_hup (sig)
8{
9   Signal = sig;
10}
11
12private define test_signal (sig, func, old_func)
13{
14   variable old;
15   signal (sig, func, &old);
16   if (_eqs (old, old_func))
17     return;
18   failed ("signal ($sig,$func,$old_func), got $old"$);
19}
20
21test_signal (SIGHUP, &handle_hup, SIG_DFL);
22test_signal (SIGHUP, SIG_APP, &handle_hup);
23test_signal (SIGHUP, SIG_DFL, SIG_DFL);
24test_signal (SIGHUP, SIG_IGN, SIG_DFL);
25test_signal (SIGHUP, &handle_hup, SIG_IGN);
26
27private define test_signal (sig, func)
28{
29   Signal = 0;
30   signal (sig, func);
31   () = kill (getpid (), sig);
32   variable count = 10;
33   while (count and (Signal == 0))
34     {
35	sleep (1);
36	count--;
37     }
38   if (Signal != sig)
39     failed ("signal %d not caught, count=%d", sig, count);
40}
41test_signal (SIGHUP, &handle_hup);
42
43private define sigalrm_handler (sig)
44{
45   if (sig != SIGALRM)
46     failed ("alarm");
47   throw MathError;
48}
49signal (SIGALRM, &sigalrm_handler);
50
51private define test_sigalarm ()
52{
53   print ("\tPausing for 2 seconds for alarm test");
54   alarm (2);
55   try
56     {
57	while (1)
58	  {
59	     sleep (1);
60	     print (".");
61	  }
62     }
63   catch MathError;
64   print ("\n");
65}
66
67private define test_getsetitimer ()
68{
69#ifexists setitimer
70   % check syntax
71   signal (SIGALRM, SIG_IGN);
72   variable interval = 10.0, value = 3.1, old_interval, old_value;
73   setitimer (ITIMER_REAL, value, interval);
74   setitimer (ITIMER_REAL, value, interval, &old_value, &old_interval);
75   if (abs (old_interval-interval) > 0.1)   %  adjust for timer resolution
76     failed ("setitimer: unexpected old interval");
77   (old_value, old_interval) = getitimer (ITIMER_REAL);
78   if (abs (old_interval-interval) > 0.1)   %  adjust for timer resolution
79     failed ("getitimer: unexpected old interval");
80
81   setitimer (ITIMER_REAL, interval, value, &old_interval);
82
83   signal (SIGALRM, &sigalrm_handler);
84   print ("\tPausing for 2.5 seconds for setitimer test");
85   setitimer (ITIMER_REAL, 2.5, 2.5);
86   try
87     {
88	while (1)
89	  {
90	     sleep (1);
91	     print (".");
92	  }
93     }
94   catch MathError:
95     {
96	setitimer (ITIMER_REAL, 0);
97     }
98   print ("\n");
99#endif
100}
101
102private define sigint_handler (sig)
103{
104   if (sig != SIGINT)
105     failed ("sigint_handler");
106   throw UserBreakError;
107}
108
109private define test_sigsuspend ()
110{
111   if (NULL != getenv ("MAKERUNNING"))
112     {
113	print ("\t(make detected: skipping test_sigsuspend)\n");
114	return;
115     }
116
117   signal (SIGINT, &sigint_handler);
118   print ("\tNow try pressing ^C in next 5 seconds...");
119   alarm (5);
120   try
121     sigsuspend ([SIGINT, SIGTSTP]);
122   catch UserBreakError;
123   catch MathError;
124   print ("\n");
125}
126
127private define test_sigprocmask ()
128{
129   variable oldmask, origmask;
130   sigprocmask (SIG_SETMASK, SIGHUP, &origmask);
131   sigprocmask (SIG_BLOCK, SIGINT, &oldmask);
132
133   if (orelse
134       {length (oldmask) != 1}
135       {oldmask[0] != SIGHUP})
136     failed ("sigprocmask: expected to see SIGHUP in the mask");
137
138   sigprocmask (SIG_UNBLOCK, SIGHUP, &oldmask);
139   if (orelse
140       {length (oldmask) != 2}
141       {(0 == length (where (oldmask == SIGHUP)))}
142       {(0 == length (where (oldmask == SIGINT)))})
143     failed ("sigprocmask: expected to see SIGINT and SIGHUP in the mask");
144
145   sigprocmask (SIG_SETMASK, origmask, &oldmask);
146   if (orelse
147       {length (oldmask) != 1}
148       {oldmask[0] != SIGINT})
149     failed ("sigprocmask: expected to see SIGINT in the mask");
150}
151
152$1 = getenv ("SLSYSWRAP_TEST");
153
154if (($1 == NULL) || (atoi ($1) == 0))
155{
156   test_sigalarm ();
157   test_getsetitimer ();
158   test_sigsuspend ();
159}
160
161test_sigprocmask ();
162
163% Interrupts are tiggered by signals that interrupt system calls.
164% These tests here are design to exercise that library interrupt hook
165% data structures.
166private variable Interrupt_Hook_A_Fired = 0;
167private variable Interrupt_Hook_B_Fired = 0;
168private define interrupt_hook_a ()
169{
170   Interrupt_Hook_A_Fired = 1;
171   return 0;
172}
173
174private define interrupt_hook_b ()
175{
176   Interrupt_Hook_B_Fired = 1;
177   return 0;
178}
179
180private define add_interrupt_hooks ()
181{
182   sltest_add_interrupt_hook (&interrupt_hook_a);
183   sltest_add_interrupt_hook (&interrupt_hook_b);
184   sltest_add_interrupt_hook (&interrupt_hook_a);
185}
186
187private define remove_interrupt_hooks ()
188{
189   sltest_remove_interrupt_hook (&interrupt_hook_a);
190   sltest_remove_interrupt_hook (&interrupt_hook_b);
191   sltest_remove_interrupt_hook (&interrupt_hook_a);
192}
193
194private define test_interrupts ()
195{
196   add_interrupt_hooks ();
197
198   () = sltest_invoke_interrupts ();
199
200   ifnot (Interrupt_Hook_A_Fired && Interrupt_Hook_B_Fired)
201     failed ("Interrupt_Hooks were not activated");
202
203   remove_interrupt_hooks ();
204}
205test_interrupts ();
206
207print ("Ok\n");
208
209exit (0);
210
211