(signal_delivery_thread): Return a value, to avoid
[bpt/guile.git] / libguile / scmsigs.c
CommitLineData
2e1fc2e8 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004 Free Software Foundation, Inc.
adb2c53b 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
adb2c53b 7 *
73be1d9e 8 * This library is distributed in the hope that it will be useful,
0f2d19dd 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
adb2c53b 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd
JB
19\f
20
29d36c2d
RB
21#if HAVE_CONFIG_H
22# include <config.h>
23#endif
24
0f2d19dd 25#include <signal.h>
9de87eea 26#include <stdio.h>
e6e2e95a
MD
27#include <errno.h>
28
a0599745 29#include "libguile/_scm.h"
0f2d19dd 30
a0599745
MD
31#include "libguile/async.h"
32#include "libguile/eval.h"
fdc28395 33#include "libguile/root.h"
a0599745 34#include "libguile/vectors.h"
1bbd0b84 35
a0599745
MD
36#include "libguile/validate.h"
37#include "libguile/scmsigs.h"
20e6290e 38
0f2d19dd
JB
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42
1bed8c28
GH
43#ifdef HAVE_SYS_TIME_H
44#include <sys/time.h>
45#endif
46
82893676
MG
47#ifdef __MINGW32__
48#include <windows.h>
49#define alarm(sec) (0)
50/* This weird comma expression is because Sleep is void under Windows. */
51#define sleep(sec) (Sleep ((sec) * 1000), 0)
ed618cc9 52#define usleep(usec) (Sleep ((usec) / 1000), 0)
82893676
MG
53#define kill(pid, sig) raise (sig)
54#endif
55
0f2d19dd
JB
56\f
57
e1a191a8 58/* SIGRETTYPE is the type that signal handlers return. See <signal.h> */
0f2d19dd
JB
59
60#ifdef RETSIGTYPE
e1a191a8 61# define SIGRETTYPE RETSIGTYPE
0f2d19dd 62#else
e1a191a8
GH
63# ifdef STDC_HEADERS
64# define SIGRETTYPE void
65# else
66# define SIGRETTYPE int
67# endif
0f2d19dd
JB
68#endif
69
70\f
71
e1a191a8 72/* take_signal is installed as the C signal handler whenever a Scheme
9de87eea
MV
73 handler is set. When a signal arrives, take_signal will write a
74 byte into the 'signal pipe'. The 'signal delivery thread' will
75 read this pipe and queue the appropriate asyncs.
76
77 When Guile is built without threads, the signal handler will
78 install the async directly.
79*/
0f2d19dd 80
0f2d19dd 81
2fbc8609 82/* Scheme vectors with information about a signal. signal_handlers
9de87eea
MV
83 contains the handler procedure or #f, signal_handler_asyncs
84 contains the thunk to be marked as an async when the signal arrives
85 (or the cell with the thunk in a singlethreaded Guile), and
dbbaa07c
MV
86 signal_handler_threads points to the thread that a signal should be
87 delivered to.
2fbc8609 88*/
e1a191a8 89static SCM *signal_handlers;
9de87eea 90static SCM signal_handler_asyncs;
2fbc8609 91static SCM signal_handler_threads;
0f2d19dd 92
e1a191a8
GH
93/* saves the original C handlers, when a new handler is installed.
94 set to SIG_ERR if the original handler is installed. */
95#ifdef HAVE_SIGACTION
96static struct sigaction orig_handlers[NSIG];
97#else
da6e81b6 98static SIGRETTYPE (*orig_handlers[NSIG])(int);
0f2d19dd
JB
99#endif
100
9de87eea
MV
101static SCM
102close_1 (SCM proc, SCM arg)
103{
104 return scm_primitive_eval_x (scm_list_3 (scm_sym_lambda, SCM_EOL,
105 scm_list_2 (proc, arg)));
106}
107
108#if SCM_USE_PTHREAD_THREADS
109
110static int signal_pipe[2];
dbbaa07c 111
e1a191a8
GH
112static SIGRETTYPE
113take_signal (int signum)
114{
9de87eea
MV
115 char sigbyte = signum;
116 write (signal_pipe[1], &sigbyte, 1);
117
2fbc8609
MV
118#ifndef HAVE_SIGACTION
119 signal (signum, take_signal);
120#endif
e1a191a8 121}
0f2d19dd 122
9de87eea
MV
123static SCM
124signal_delivery_thread (void *data)
e1a191a8 125{
9de87eea
MV
126 sigset_t all_sigs;
127 scm_t_guile_ticket ticket;
128 int n, sig;
129 char sigbyte;
130
131 sigfillset (&all_sigs);
132 scm_i_pthread_sigmask (SIG_SETMASK, &all_sigs, NULL);
133
134 while (1)
135 {
136 ticket = scm_leave_guile ();
137 n = read (signal_pipe[0], &sigbyte, 1);
138 sig = sigbyte;
139 scm_enter_guile (ticket);
140 if (n == 1 && sig >= 0 && sig < NSIG)
141 {
142 SCM h, t;
143
144 h = SCM_SIMPLE_VECTOR_REF (signal_handler_asyncs, sig);
145 t = SCM_SIMPLE_VECTOR_REF (signal_handler_threads, sig);
146 if (scm_is_true (h))
147 scm_system_async_mark_for_thread (h, t);
148 }
149 else if (n < 0 && errno != EINTR)
150 perror ("error in signal delivery thread");
151 }
229a0710
NJ
152
153 return SCM_UNSPECIFIED; /* not reached */
2fbc8609 154}
e1a191a8 155
9de87eea
MV
156static void
157start_signal_delivery_thread (void)
2fbc8609 158{
9de87eea
MV
159 if (pipe (signal_pipe) != 0)
160 scm_syserror (NULL);
161 scm_spawn_thread (signal_delivery_thread, NULL,
162 scm_handle_by_message, "signal delivery thread");
0f2d19dd
JB
163}
164
9de87eea
MV
165static void
166ensure_signal_delivery_thread ()
167{
168 static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
169 scm_i_pthread_once (&once, start_signal_delivery_thread);
170}
dbbaa07c 171
9de87eea 172#else /* !SCM_USE_PTHREAD_THREADS */
dbbaa07c 173
9de87eea
MV
174static SIGRETTYPE
175take_signal (int signum)
dbbaa07c 176{
9de87eea
MV
177 SCM cell = SCM_SIMPLE_VECTOR_REF (signal_handler_asyncs, signum);
178 scm_i_thread *t = SCM_I_CURRENT_THREAD;
179
180 if (scm_is_false (SCM_CDR (cell)))
dbbaa07c 181 {
9de87eea
MV
182 SCM_SETCDR (cell, t->active_asyncs);
183 t->active_asyncs = cell;
184 t->pending_asyncs = 1;
dbbaa07c 185 }
9de87eea
MV
186
187#ifndef HAVE_SIGACTION
188 signal (signum, take_signal);
189#endif
dbbaa07c
MV
190}
191
9de87eea
MV
192static void
193ensure_signal_delivery_thread ()
dbbaa07c 194{
9de87eea
MV
195 return;
196}
dbbaa07c 197
9de87eea 198#endif /* !SCM_USE_PTHREAD_THREADS */
dbbaa07c 199
9de87eea
MV
200static void
201install_handler (int signum, SCM thread, SCM handler)
202{
7888309b 203 if (scm_is_false (handler))
dbbaa07c 204 {
4057a3e0 205 SCM_SIMPLE_VECTOR_SET (*signal_handlers, signum, SCM_BOOL_F);
9de87eea 206 SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs, signum, SCM_BOOL_F);
dbbaa07c
MV
207 }
208 else
209 {
9de87eea
MV
210 SCM async = close_1 (handler, scm_from_int (signum));
211#if !SCM_USE_PTHREAD_THREADS
212 async = scm_cons (async, SCM_BOOL_F);
213#endif
4057a3e0 214 SCM_SIMPLE_VECTOR_SET (*signal_handlers, signum, handler);
9de87eea 215 SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs, signum, async);
dbbaa07c
MV
216 }
217
9de87eea 218 SCM_SIMPLE_VECTOR_SET (signal_handler_threads, signum, thread);
dbbaa07c
MV
219}
220
9de87eea
MV
221SCM
222scm_sigaction (SCM signum, SCM handler, SCM flags)
dbbaa07c 223{
9de87eea 224 return scm_sigaction_for_thread (signum, handler, flags, SCM_UNDEFINED);
dbbaa07c
MV
225}
226
e1a191a8 227/* user interface for installation of signal handlers. */
2fbc8609
MV
228SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0,
229 (SCM signum, SCM handler, SCM flags, SCM thread),
0d172d3f 230 "Install or report the signal handler for a specified signal.\n\n"
b380b885
MD
231 "@var{signum} is the signal number, which can be specified using the value\n"
232 "of variables such as @code{SIGINT}.\n\n"
2fbc8609 233 "If @var{handler} is omitted, @code{sigaction} returns a pair: the\n"
b380b885
MD
234 "CAR is the current\n"
235 "signal hander, which will be either an integer with the value @code{SIG_DFL}\n"
236 "(default action) or @code{SIG_IGN} (ignore), or the Scheme procedure which\n"
237 "handles the signal, or @code{#f} if a non-Scheme procedure handles the\n"
238 "signal. The CDR contains the current @code{sigaction} flags for the handler.\n\n"
2fbc8609
MV
239 "If @var{handler} is provided, it is installed as the new handler for\n"
240 "@var{signum}. @var{handler} can be a Scheme procedure taking one\n"
b380b885
MD
241 "argument, or the value of @code{SIG_DFL} (default action) or\n"
242 "@code{SIG_IGN} (ignore), or @code{#f} to restore whatever signal handler\n"
2fbc8609
MV
243 "was installed before @code{sigaction} was first used. When\n"
244 "a scheme procedure has been specified, that procedure will run\n"
245 "in the given @var{thread}. When no thread has been given, the\n"
246 "thread that made this call to @code{sigaction} is used.\n"
247 "Flags can "
b380b885 248 "optionally be specified for the new handler (@code{SA_RESTART} will\n"
0d172d3f 249 "always be added if it's available and the system is using restartable\n"
b380b885
MD
250 "system calls.) The return value is a pair with information about the\n"
251 "old handler as described above.\n\n"
252 "This interface does not provide access to the \"signal blocking\"\n"
253 "facility. Maybe this is not needed, since the thread support may\n"
254 "provide solutions to the problem of consistent access to data\n"
255 "structures.")
2fbc8609 256#define FUNC_NAME s_scm_sigaction_for_thread
e1a191a8
GH
257{
258 int csig;
259#ifdef HAVE_SIGACTION
260 struct sigaction action;
261 struct sigaction old_action;
262#else
af68e5e5 263 SIGRETTYPE (* chandler) (int) = SIG_DFL;
e1a191a8
GH
264 SIGRETTYPE (* old_chandler) (int);
265#endif
266 int query_only = 0;
267 int save_handler = 0;
34d19ef6 268
e1a191a8
GH
269 SCM old_handler;
270
a55c2b68
MV
271 csig = scm_to_signed_integer (signum, 0, NSIG-1);
272
7ee92fce
GH
273#if defined(HAVE_SIGACTION)
274#if defined(SA_RESTART) && defined(HAVE_RESTARTABLE_SYSCALLS)
275 /* don't allow SA_RESTART to be omitted if HAVE_RESTARTABLE_SYSCALLS
276 is defined, since libguile would be likely to produce spurious
277 EINTR errors. */
e1a191a8
GH
278 action.sa_flags = SA_RESTART;
279#else
280 action.sa_flags = 0;
281#endif
282 if (!SCM_UNBNDP (flags))
a55c2b68 283 action.sa_flags |= scm_to_int (flags);
e1a191a8 284 sigemptyset (&action.sa_mask);
4feac0b9
MV
285#endif
286
2fbc8609
MV
287 if (SCM_UNBNDP (thread))
288 thread = scm_current_thread ();
289 else
dbbaa07c
MV
290 {
291 SCM_VALIDATE_THREAD (4, thread);
292 if (scm_c_thread_exited_p (thread))
293 SCM_MISC_ERROR ("thread has already exited", SCM_EOL);
294 }
4feac0b9 295
9de87eea
MV
296 ensure_signal_delivery_thread ();
297
298 SCM_CRITICAL_SECTION_START;
4057a3e0 299 old_handler = SCM_SIMPLE_VECTOR_REF (*signal_handlers, csig);
e1a191a8
GH
300 if (SCM_UNBNDP (handler))
301 query_only = 1;
e11e83f3 302 else if (scm_is_integer (handler))
e1a191a8 303 {
9de87eea
MV
304 long handler_int = scm_to_long (handler);
305
306 if (handler_int == (long) SIG_DFL || handler_int == (long) SIG_IGN)
e1a191a8
GH
307 {
308#ifdef HAVE_SIGACTION
9de87eea 309 action.sa_handler = (SIGRETTYPE (*) (int)) handler_int;
e1a191a8 310#else
9de87eea 311 chandler = (SIGRETTYPE (*) (int)) handler_int;
e1a191a8 312#endif
dbbaa07c 313 install_handler (csig, SCM_BOOL_F, SCM_BOOL_F);
e1a191a8
GH
314 }
315 else
1bbd0b84 316 SCM_OUT_OF_RANGE (2, handler);
e1a191a8 317 }
7888309b 318 else if (scm_is_false (handler))
e1a191a8
GH
319 {
320 /* restore the default handler. */
321#ifdef HAVE_SIGACTION
322 if (orig_handlers[csig].sa_handler == SIG_ERR)
323 query_only = 1;
324 else
325 {
326 action = orig_handlers[csig];
327 orig_handlers[csig].sa_handler = SIG_ERR;
dbbaa07c 328 install_handler (csig, SCM_BOOL_F, SCM_BOOL_F);
e1a191a8
GH
329 }
330#else
331 if (orig_handlers[csig] == SIG_ERR)
332 query_only = 1;
333 else
334 {
335 chandler = orig_handlers[csig];
336 orig_handlers[csig] = SIG_ERR;
dbbaa07c 337 install_handler (csig, SCM_BOOL_F, SCM_BOOL_F);
e1a191a8
GH
338 }
339#endif
adb2c53b 340 }
e1a191a8
GH
341 else
342 {
43067cec 343 SCM_VALIDATE_PROC (2, handler);
e1a191a8
GH
344#ifdef HAVE_SIGACTION
345 action.sa_handler = take_signal;
346 if (orig_handlers[csig].sa_handler == SIG_ERR)
347 save_handler = 1;
348#else
349 chandler = take_signal;
350 if (orig_handlers[csig] == SIG_ERR)
351 save_handler = 1;
352#endif
dbbaa07c 353 install_handler (csig, thread, handler);
e1a191a8 354 }
adb2c53b 355
0d172d3f
MV
356 /* XXX - Silently ignore setting handlers for `program error signals'
357 because they can't currently be handled by Scheme code.
358 */
359
360 switch (csig)
361 {
362 /* This list of program error signals is from the GNU Libc
363 Reference Manual */
364 case SIGFPE:
365 case SIGILL:
366 case SIGSEGV:
82893676 367#ifdef SIGBUS
0d172d3f 368 case SIGBUS:
82893676 369#endif
0d172d3f 370 case SIGABRT:
6732de1b 371#if defined(SIGIOT) && (SIGIOT != SIGABRT)
0d172d3f
MV
372 case SIGIOT:
373#endif
82893676 374#ifdef SIGTRAP
0d172d3f 375 case SIGTRAP:
82893676 376#endif
0d172d3f
MV
377#ifdef SIGEMT
378 case SIGEMT:
379#endif
adb2c53b 380#ifdef SIGSYS
0d172d3f 381 case SIGSYS:
adb2c53b 382#endif
0d172d3f
MV
383 query_only = 1;
384 }
385
e1a191a8
GH
386#ifdef HAVE_SIGACTION
387 if (query_only)
388 {
389 if (sigaction (csig, 0, &old_action) == -1)
1bbd0b84 390 SCM_SYSERROR;
e1a191a8
GH
391 }
392 else
393 {
394 if (sigaction (csig, &action , &old_action) == -1)
1bbd0b84 395 SCM_SYSERROR;
e1a191a8
GH
396 if (save_handler)
397 orig_handlers[csig] = old_action;
398 }
399 if (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN)
b9bd8526 400 old_handler = scm_from_long ((long) old_action.sa_handler);
9de87eea 401 SCM_CRITICAL_SECTION_END;
e11e83f3 402 return scm_cons (old_handler, scm_from_int (old_action.sa_flags));
e1a191a8
GH
403#else
404 if (query_only)
405 {
406 if ((old_chandler = signal (csig, SIG_IGN)) == SIG_ERR)
1bbd0b84 407 SCM_SYSERROR;
e1a191a8 408 if (signal (csig, old_chandler) == SIG_ERR)
1bbd0b84 409 SCM_SYSERROR;
e1a191a8
GH
410 }
411 else
412 {
413 if ((old_chandler = signal (csig, chandler)) == SIG_ERR)
1bbd0b84 414 SCM_SYSERROR;
e1a191a8
GH
415 if (save_handler)
416 orig_handlers[csig] = old_chandler;
417 }
418 if (old_chandler == SIG_DFL || old_chandler == SIG_IGN)
b9bd8526 419 old_handler = scm_from_long ((long) old_chandler);
9de87eea 420 SCM_CRITICAL_SECTION_END;
e11e83f3 421 return scm_cons (old_handler, scm_from_int (0));
0f2d19dd 422#endif
e1a191a8 423}
1bbd0b84 424#undef FUNC_NAME
e1a191a8 425
adb2c53b 426SCM_DEFINE (scm_restore_signals, "restore-signals", 0, 0, 0,
1bbd0b84 427 (void),
b380b885
MD
428 "Return all signal handlers to the values they had before any call to\n"
429 "@code{sigaction} was made. The return value is unspecified.")
1bbd0b84 430#define FUNC_NAME s_scm_restore_signals
e1a191a8
GH
431{
432 int i;
e1a191a8
GH
433 for (i = 0; i < NSIG; i++)
434 {
435#ifdef HAVE_SIGACTION
436 if (orig_handlers[i].sa_handler != SIG_ERR)
437 {
438 if (sigaction (i, &orig_handlers[i], NULL) == -1)
1bbd0b84 439 SCM_SYSERROR;
e1a191a8 440 orig_handlers[i].sa_handler = SIG_ERR;
4057a3e0 441 SCM_SIMPLE_VECTOR_SET (*signal_handlers, i, SCM_BOOL_F);
e1a191a8
GH
442 }
443#else
444 if (orig_handlers[i] != SIG_ERR)
445 {
446 if (signal (i, orig_handlers[i]) == SIG_ERR)
1bbd0b84 447 SCM_SYSERROR;
e1a191a8 448 orig_handlers[i] = SIG_ERR;
4057a3e0 449 SCM_SIMPLE_VECTOR_SET (*signal_handlers, i, SCM_BOOL_F);
e1a191a8
GH
450 }
451#endif
452 }
453 return SCM_UNSPECIFIED;
454}
1bbd0b84 455#undef FUNC_NAME
0f2d19dd 456
adb2c53b 457SCM_DEFINE (scm_alarm, "alarm", 1, 0, 0,
1bbd0b84 458 (SCM i),
b380b885
MD
459 "Set a timer to raise a @code{SIGALRM} signal after the specified\n"
460 "number of seconds (an integer). It's advisable to install a signal\n"
461 "handler for\n"
462 "@code{SIGALRM} beforehand, since the default action is to terminate\n"
463 "the process.\n\n"
464 "The return value indicates the time remaining for the previous alarm,\n"
465 "if any. The new value replaces the previous alarm. If there was\n"
466 "no previous alarm, the return value is zero.")
1bbd0b84 467#define FUNC_NAME s_scm_alarm
0f2d19dd 468{
a55c2b68 469 return scm_from_uint (alarm (scm_to_uint (i)));
0f2d19dd 470}
1bbd0b84 471#undef FUNC_NAME
0f2d19dd 472
53f8a0d2
RB
473#ifdef HAVE_SETITIMER
474SCM_DEFINE (scm_setitimer, "setitimer", 5, 0, 0,
475 (SCM which_timer,
476 SCM interval_seconds, SCM interval_microseconds,
477 SCM value_seconds, SCM value_microseconds),
478 "Set the timer specified by @var{which_timer} according to the given\n"
479 "@var{interval_seconds}, @var{interval_microseconds},\n"
480 "@var{value_seconds}, and @var{value_microseconds} values.\n"
481 "\n"
482 "Return information about the timer's previous setting."
483 "\n"
484 "Errors are handled as described in the guile info pages under ``POSIX\n"
485 "Interface Conventions''.\n"
486 "\n"
9401323e 487 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
53f8a0d2
RB
488 "and @code{ITIMER_PROF}.\n"
489 "\n"
490 "The return value will be a list of two cons pairs representing the\n"
491 "current state of the given timer. The first pair is the seconds and\n"
492 "microseconds of the timer @code{it_interval}, and the second pair is\n"
9401323e 493 "the seconds and microseconds of the timer @code{it_value}.")
53f8a0d2
RB
494#define FUNC_NAME s_scm_setitimer
495{
496 int rv;
497 int c_which_timer;
498 struct itimerval new_timer;
499 struct itimerval old_timer;
500
501 c_which_timer = SCM_NUM2INT(1, which_timer);
502 new_timer.it_interval.tv_sec = SCM_NUM2LONG(2, interval_seconds);
503 new_timer.it_interval.tv_usec = SCM_NUM2LONG(3, interval_microseconds);
504 new_timer.it_value.tv_sec = SCM_NUM2LONG(4, value_seconds);
505 new_timer.it_value.tv_usec = SCM_NUM2LONG(5, value_microseconds);
506
507 SCM_SYSCALL(rv = setitimer(c_which_timer, &new_timer, &old_timer));
508
509 if(rv != 0)
510 SCM_SYSERROR;
511
b9bd8526
MV
512 return scm_list_2 (scm_cons (scm_from_long (old_timer.it_interval.tv_sec),
513 scm_from_long (old_timer.it_interval.tv_usec)),
514 scm_cons (scm_from_long (old_timer.it_value.tv_sec),
515 scm_from_long (old_timer.it_value.tv_usec)));
53f8a0d2
RB
516}
517#undef FUNC_NAME
518#endif /* HAVE_SETITIMER */
519
520#ifdef HAVE_GETITIMER
521SCM_DEFINE (scm_getitimer, "getitimer", 1, 0, 0,
522 (SCM which_timer),
523 "Return information about the timer specified by @var{which_timer}"
524 "\n"
525 "Errors are handled as described in the guile info pages under ``POSIX\n"
526 "Interface Conventions''.\n"
527 "\n"
9401323e 528 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
53f8a0d2
RB
529 "and @code{ITIMER_PROF}.\n"
530 "\n"
531 "The return value will be a list of two cons pairs representing the\n"
532 "current state of the given timer. The first pair is the seconds and\n"
533 "microseconds of the timer @code{it_interval}, and the second pair is\n"
9401323e 534 "the seconds and microseconds of the timer @code{it_value}.")
53f8a0d2
RB
535#define FUNC_NAME s_scm_getitimer
536{
537 int rv;
538 int c_which_timer;
539 struct itimerval old_timer;
540
541 c_which_timer = SCM_NUM2INT(1, which_timer);
542
543 SCM_SYSCALL(rv = getitimer(c_which_timer, &old_timer));
544
545 if(rv != 0)
546 SCM_SYSERROR;
547
b9bd8526
MV
548 return scm_list_2 (scm_cons (scm_from_long (old_timer.it_interval.tv_sec),
549 scm_from_long (old_timer.it_interval.tv_usec)),
550 scm_cons (scm_from_long (old_timer.it_value.tv_sec),
551 scm_from_long (old_timer.it_value.tv_usec)));
53f8a0d2
RB
552}
553#undef FUNC_NAME
554#endif /* HAVE_GETITIMER */
555
0e958795 556#ifdef HAVE_PAUSE
adb2c53b 557SCM_DEFINE (scm_pause, "pause", 0, 0, 0,
1bbd0b84 558 (),
b380b885
MD
559 "Pause the current process (thread?) until a signal arrives whose\n"
560 "action is to either terminate the current process or invoke a\n"
561 "handler procedure. The return value is unspecified.")
1bbd0b84 562#define FUNC_NAME s_scm_pause
0f2d19dd
JB
563{
564 pause ();
565 return SCM_UNSPECIFIED;
566}
1bbd0b84 567#undef FUNC_NAME
0e958795 568#endif
0f2d19dd 569
adb2c53b 570SCM_DEFINE (scm_sleep, "sleep", 1, 0, 0,
1bbd0b84 571 (SCM i),
b380b885
MD
572 "Wait for the given number of seconds (an integer) or until a signal\n"
573 "arrives. The return value is zero if the time elapses or the number\n"
574 "of seconds remaining otherwise.")
1bbd0b84 575#define FUNC_NAME s_scm_sleep
0f2d19dd 576{
9de87eea 577 return scm_from_uint (scm_std_sleep (scm_to_uint (i)));
0f2d19dd 578}
1bbd0b84 579#undef FUNC_NAME
0f2d19dd 580
adb2c53b 581SCM_DEFINE (scm_usleep, "usleep", 1, 0, 0,
1bbd0b84 582 (SCM i),
a55c2b68 583 "Sleep for @var{i} microseconds.")
1bbd0b84 584#define FUNC_NAME s_scm_usleep
ce874f2d 585{
9de87eea 586 return scm_from_ulong (scm_std_usleep (scm_to_ulong (i)));
b74f4728 587}
1bbd0b84 588#undef FUNC_NAME
ce874f2d 589
adb2c53b 590SCM_DEFINE (scm_raise, "raise", 1, 0, 0,
1bbd0b84 591 (SCM sig),
b380b885
MD
592 "Sends a specified signal @var{sig} to the current process, where\n"
593 "@var{sig} is as described for the kill procedure.")
1bbd0b84 594#define FUNC_NAME s_scm_raise
0f2d19dd 595{
a55c2b68 596 if (kill (getpid (), scm_to_int (sig)) != 0)
1bbd0b84 597 SCM_SYSERROR;
e1a191a8 598 return SCM_UNSPECIFIED;
0f2d19dd 599}
1bbd0b84 600#undef FUNC_NAME
0f2d19dd
JB
601
602\f
0f2d19dd 603
e1a191a8
GH
604void
605scm_init_scmsigs ()
0f2d19dd 606{
e1a191a8
GH
607 int i;
608
609 signal_handlers =
86d31dfe
MV
610 SCM_VARIABLE_LOC (scm_c_define ("signal-handlers",
611 scm_c_make_vector (NSIG, SCM_BOOL_F)));
9de87eea 612 signal_handler_asyncs =
dbbaa07c 613 scm_permanent_object (scm_c_make_vector (NSIG, SCM_BOOL_F));
2fbc8609
MV
614 signal_handler_threads =
615 scm_permanent_object (scm_c_make_vector (NSIG, SCM_BOOL_F));
e1a191a8
GH
616
617 for (i = 0; i < NSIG; i++)
618 {
e1a191a8
GH
619#ifdef HAVE_SIGACTION
620 orig_handlers[i].sa_handler = SIG_ERR;
840ae05d 621
e1a191a8
GH
622#else
623 orig_handlers[i] = SIG_ERR;
0f2d19dd 624#endif
840ae05d 625
08b8c694 626#ifdef HAVE_RESTARTABLE_SYSCALLS
7ee92fce 627 /* If HAVE_RESTARTABLE_SYSCALLS is defined, it's important that
adb2c53b 628 signals really are restartable. don't rely on the same
7ee92fce
GH
629 run-time that configure got: reset the default for every signal.
630 */
631#ifdef HAVE_SIGINTERRUPT
632 siginterrupt (i, 0);
de881428 633#elif defined(SA_RESTART)
840ae05d
JB
634 {
635 struct sigaction action;
636
637 sigaction (i, NULL, &action);
638 if (!(action.sa_flags & SA_RESTART))
639 {
3efb80f2 640 action.sa_flags |= SA_RESTART;
840ae05d
JB
641 sigaction (i, &action, NULL);
642 }
643 }
7ee92fce
GH
644#endif
645 /* if neither siginterrupt nor SA_RESTART are available we may
646 as well assume that signals are always restartable. */
840ae05d 647#endif
e1a191a8 648 }
1cc91f1b 649
b9bd8526
MV
650 scm_c_define ("NSIG", scm_from_long (NSIG));
651 scm_c_define ("SIG_IGN", scm_from_long ((long) SIG_IGN));
652 scm_c_define ("SIG_DFL", scm_from_long ((long) SIG_DFL));
e1a191a8 653#ifdef SA_NOCLDSTOP
b9bd8526 654 scm_c_define ("SA_NOCLDSTOP", scm_from_long (SA_NOCLDSTOP));
0f2d19dd 655#endif
e1a191a8 656#ifdef SA_RESTART
b9bd8526 657 scm_c_define ("SA_RESTART", scm_from_long (SA_RESTART));
0f2d19dd 658#endif
1cc91f1b 659
53f8a0d2
RB
660#if defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER)
661 /* Stuff needed by setitimer and getitimer. */
e11e83f3
MV
662 scm_c_define ("ITIMER_REAL", scm_from_int (ITIMER_REAL));
663 scm_c_define ("ITIMER_VIRTUAL", scm_from_int (ITIMER_VIRTUAL));
664 scm_c_define ("ITIMER_PROF", scm_from_int (ITIMER_PROF));
53f8a0d2
RB
665#endif /* defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER) */
666
a0599745 667#include "libguile/scmsigs.x"
0f2d19dd
JB
668}
669
89e00824
ML
670
671/*
672 Local Variables:
673 c-file-style: "gnu"
674 End:
675*/