2006-02-01 Ludovic Courtès <ludovic.courtes@laas.fr>
[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
92205699 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
73be1d9e 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
324a5aa9
MV
123typedef struct {
124 ssize_t res;
125 int fd;
126 char *buf;
127 size_t n;
128} read_without_guile_data;
129
130static void *
131do_read_without_guile (void *raw_data)
132{
2824f4dc 133 read_without_guile_data *data = (read_without_guile_data *)raw_data;
324a5aa9
MV
134 data->res = read (data->fd, data->buf, data->n);
135 return NULL;
136}
137
138static ssize_t
139read_without_guile (int fd, char *buf, size_t n)
140{
141 read_without_guile_data data;
142 data.fd = fd;
143 data.buf = buf;
144 data.n = n;
145 scm_without_guile (do_read_without_guile, &data);
146 return data.res;
147}
148
9de87eea
MV
149static SCM
150signal_delivery_thread (void *data)
e1a191a8 151{
9de87eea 152 sigset_t all_sigs;
9de87eea
MV
153 int n, sig;
154 char sigbyte;
155
156 sigfillset (&all_sigs);
157 scm_i_pthread_sigmask (SIG_SETMASK, &all_sigs, NULL);
158
159 while (1)
160 {
324a5aa9 161 n = read_without_guile (signal_pipe[0], &sigbyte, 1);
9de87eea 162 sig = sigbyte;
9de87eea
MV
163 if (n == 1 && sig >= 0 && sig < NSIG)
164 {
165 SCM h, t;
166
167 h = SCM_SIMPLE_VECTOR_REF (signal_handler_asyncs, sig);
168 t = SCM_SIMPLE_VECTOR_REF (signal_handler_threads, sig);
169 if (scm_is_true (h))
170 scm_system_async_mark_for_thread (h, t);
171 }
172 else if (n < 0 && errno != EINTR)
173 perror ("error in signal delivery thread");
174 }
229a0710
NJ
175
176 return SCM_UNSPECIFIED; /* not reached */
2fbc8609 177}
e1a191a8 178
9de87eea
MV
179static void
180start_signal_delivery_thread (void)
2fbc8609 181{
9de87eea
MV
182 if (pipe (signal_pipe) != 0)
183 scm_syserror (NULL);
184 scm_spawn_thread (signal_delivery_thread, NULL,
185 scm_handle_by_message, "signal delivery thread");
0f2d19dd
JB
186}
187
9de87eea
MV
188static void
189ensure_signal_delivery_thread ()
190{
191 static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
192 scm_i_pthread_once (&once, start_signal_delivery_thread);
193}
dbbaa07c 194
9de87eea 195#else /* !SCM_USE_PTHREAD_THREADS */
dbbaa07c 196
9de87eea
MV
197static SIGRETTYPE
198take_signal (int signum)
dbbaa07c 199{
9de87eea
MV
200 SCM cell = SCM_SIMPLE_VECTOR_REF (signal_handler_asyncs, signum);
201 scm_i_thread *t = SCM_I_CURRENT_THREAD;
202
203 if (scm_is_false (SCM_CDR (cell)))
dbbaa07c 204 {
9de87eea
MV
205 SCM_SETCDR (cell, t->active_asyncs);
206 t->active_asyncs = cell;
207 t->pending_asyncs = 1;
dbbaa07c 208 }
9de87eea
MV
209
210#ifndef HAVE_SIGACTION
211 signal (signum, take_signal);
212#endif
dbbaa07c
MV
213}
214
9de87eea
MV
215static void
216ensure_signal_delivery_thread ()
dbbaa07c 217{
9de87eea
MV
218 return;
219}
dbbaa07c 220
9de87eea 221#endif /* !SCM_USE_PTHREAD_THREADS */
dbbaa07c 222
9de87eea
MV
223static void
224install_handler (int signum, SCM thread, SCM handler)
225{
7888309b 226 if (scm_is_false (handler))
dbbaa07c 227 {
4057a3e0 228 SCM_SIMPLE_VECTOR_SET (*signal_handlers, signum, SCM_BOOL_F);
9de87eea 229 SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs, signum, SCM_BOOL_F);
dbbaa07c
MV
230 }
231 else
232 {
9de87eea
MV
233 SCM async = close_1 (handler, scm_from_int (signum));
234#if !SCM_USE_PTHREAD_THREADS
235 async = scm_cons (async, SCM_BOOL_F);
236#endif
4057a3e0 237 SCM_SIMPLE_VECTOR_SET (*signal_handlers, signum, handler);
9de87eea 238 SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs, signum, async);
dbbaa07c
MV
239 }
240
9de87eea 241 SCM_SIMPLE_VECTOR_SET (signal_handler_threads, signum, thread);
dbbaa07c
MV
242}
243
9de87eea
MV
244SCM
245scm_sigaction (SCM signum, SCM handler, SCM flags)
dbbaa07c 246{
9de87eea 247 return scm_sigaction_for_thread (signum, handler, flags, SCM_UNDEFINED);
dbbaa07c
MV
248}
249
e1a191a8 250/* user interface for installation of signal handlers. */
2fbc8609
MV
251SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0,
252 (SCM signum, SCM handler, SCM flags, SCM thread),
0d172d3f 253 "Install or report the signal handler for a specified signal.\n\n"
b380b885
MD
254 "@var{signum} is the signal number, which can be specified using the value\n"
255 "of variables such as @code{SIGINT}.\n\n"
2fbc8609 256 "If @var{handler} is omitted, @code{sigaction} returns a pair: the\n"
b380b885
MD
257 "CAR is the current\n"
258 "signal hander, which will be either an integer with the value @code{SIG_DFL}\n"
259 "(default action) or @code{SIG_IGN} (ignore), or the Scheme procedure which\n"
260 "handles the signal, or @code{#f} if a non-Scheme procedure handles the\n"
261 "signal. The CDR contains the current @code{sigaction} flags for the handler.\n\n"
2fbc8609
MV
262 "If @var{handler} is provided, it is installed as the new handler for\n"
263 "@var{signum}. @var{handler} can be a Scheme procedure taking one\n"
b380b885
MD
264 "argument, or the value of @code{SIG_DFL} (default action) or\n"
265 "@code{SIG_IGN} (ignore), or @code{#f} to restore whatever signal handler\n"
2fbc8609
MV
266 "was installed before @code{sigaction} was first used. When\n"
267 "a scheme procedure has been specified, that procedure will run\n"
268 "in the given @var{thread}. When no thread has been given, the\n"
269 "thread that made this call to @code{sigaction} is used.\n"
270 "Flags can "
b380b885 271 "optionally be specified for the new handler (@code{SA_RESTART} will\n"
0d172d3f 272 "always be added if it's available and the system is using restartable\n"
b380b885
MD
273 "system calls.) The return value is a pair with information about the\n"
274 "old handler as described above.\n\n"
275 "This interface does not provide access to the \"signal blocking\"\n"
276 "facility. Maybe this is not needed, since the thread support may\n"
277 "provide solutions to the problem of consistent access to data\n"
278 "structures.")
2fbc8609 279#define FUNC_NAME s_scm_sigaction_for_thread
e1a191a8
GH
280{
281 int csig;
282#ifdef HAVE_SIGACTION
283 struct sigaction action;
284 struct sigaction old_action;
285#else
af68e5e5 286 SIGRETTYPE (* chandler) (int) = SIG_DFL;
e1a191a8
GH
287 SIGRETTYPE (* old_chandler) (int);
288#endif
289 int query_only = 0;
290 int save_handler = 0;
34d19ef6 291
e1a191a8
GH
292 SCM old_handler;
293
a55c2b68
MV
294 csig = scm_to_signed_integer (signum, 0, NSIG-1);
295
7ee92fce
GH
296#if defined(HAVE_SIGACTION)
297#if defined(SA_RESTART) && defined(HAVE_RESTARTABLE_SYSCALLS)
298 /* don't allow SA_RESTART to be omitted if HAVE_RESTARTABLE_SYSCALLS
299 is defined, since libguile would be likely to produce spurious
300 EINTR errors. */
e1a191a8
GH
301 action.sa_flags = SA_RESTART;
302#else
303 action.sa_flags = 0;
304#endif
305 if (!SCM_UNBNDP (flags))
a55c2b68 306 action.sa_flags |= scm_to_int (flags);
e1a191a8 307 sigemptyset (&action.sa_mask);
4feac0b9
MV
308#endif
309
2fbc8609
MV
310 if (SCM_UNBNDP (thread))
311 thread = scm_current_thread ();
312 else
dbbaa07c
MV
313 {
314 SCM_VALIDATE_THREAD (4, thread);
315 if (scm_c_thread_exited_p (thread))
316 SCM_MISC_ERROR ("thread has already exited", SCM_EOL);
317 }
4feac0b9 318
9de87eea
MV
319 ensure_signal_delivery_thread ();
320
321 SCM_CRITICAL_SECTION_START;
4057a3e0 322 old_handler = SCM_SIMPLE_VECTOR_REF (*signal_handlers, csig);
e1a191a8
GH
323 if (SCM_UNBNDP (handler))
324 query_only = 1;
e11e83f3 325 else if (scm_is_integer (handler))
e1a191a8 326 {
9de87eea
MV
327 long handler_int = scm_to_long (handler);
328
329 if (handler_int == (long) SIG_DFL || handler_int == (long) SIG_IGN)
e1a191a8
GH
330 {
331#ifdef HAVE_SIGACTION
9de87eea 332 action.sa_handler = (SIGRETTYPE (*) (int)) handler_int;
e1a191a8 333#else
9de87eea 334 chandler = (SIGRETTYPE (*) (int)) handler_int;
e1a191a8 335#endif
dbbaa07c 336 install_handler (csig, SCM_BOOL_F, SCM_BOOL_F);
e1a191a8
GH
337 }
338 else
1bbd0b84 339 SCM_OUT_OF_RANGE (2, handler);
e1a191a8 340 }
7888309b 341 else if (scm_is_false (handler))
e1a191a8
GH
342 {
343 /* restore the default handler. */
344#ifdef HAVE_SIGACTION
345 if (orig_handlers[csig].sa_handler == SIG_ERR)
346 query_only = 1;
347 else
348 {
349 action = orig_handlers[csig];
350 orig_handlers[csig].sa_handler = SIG_ERR;
dbbaa07c 351 install_handler (csig, SCM_BOOL_F, SCM_BOOL_F);
e1a191a8
GH
352 }
353#else
354 if (orig_handlers[csig] == SIG_ERR)
355 query_only = 1;
356 else
357 {
358 chandler = orig_handlers[csig];
359 orig_handlers[csig] = SIG_ERR;
dbbaa07c 360 install_handler (csig, SCM_BOOL_F, SCM_BOOL_F);
e1a191a8
GH
361 }
362#endif
adb2c53b 363 }
e1a191a8
GH
364 else
365 {
43067cec 366 SCM_VALIDATE_PROC (2, handler);
e1a191a8
GH
367#ifdef HAVE_SIGACTION
368 action.sa_handler = take_signal;
369 if (orig_handlers[csig].sa_handler == SIG_ERR)
370 save_handler = 1;
371#else
372 chandler = take_signal;
373 if (orig_handlers[csig] == SIG_ERR)
374 save_handler = 1;
375#endif
dbbaa07c 376 install_handler (csig, thread, handler);
e1a191a8 377 }
adb2c53b 378
0d172d3f
MV
379 /* XXX - Silently ignore setting handlers for `program error signals'
380 because they can't currently be handled by Scheme code.
381 */
382
383 switch (csig)
384 {
385 /* This list of program error signals is from the GNU Libc
386 Reference Manual */
387 case SIGFPE:
388 case SIGILL:
389 case SIGSEGV:
82893676 390#ifdef SIGBUS
0d172d3f 391 case SIGBUS:
82893676 392#endif
0d172d3f 393 case SIGABRT:
6732de1b 394#if defined(SIGIOT) && (SIGIOT != SIGABRT)
0d172d3f
MV
395 case SIGIOT:
396#endif
82893676 397#ifdef SIGTRAP
0d172d3f 398 case SIGTRAP:
82893676 399#endif
0d172d3f
MV
400#ifdef SIGEMT
401 case SIGEMT:
402#endif
adb2c53b 403#ifdef SIGSYS
0d172d3f 404 case SIGSYS:
adb2c53b 405#endif
0d172d3f
MV
406 query_only = 1;
407 }
408
e1a191a8
GH
409#ifdef HAVE_SIGACTION
410 if (query_only)
411 {
412 if (sigaction (csig, 0, &old_action) == -1)
1bbd0b84 413 SCM_SYSERROR;
e1a191a8
GH
414 }
415 else
416 {
417 if (sigaction (csig, &action , &old_action) == -1)
1bbd0b84 418 SCM_SYSERROR;
e1a191a8
GH
419 if (save_handler)
420 orig_handlers[csig] = old_action;
421 }
422 if (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN)
b9bd8526 423 old_handler = scm_from_long ((long) old_action.sa_handler);
9de87eea 424 SCM_CRITICAL_SECTION_END;
e11e83f3 425 return scm_cons (old_handler, scm_from_int (old_action.sa_flags));
e1a191a8
GH
426#else
427 if (query_only)
428 {
429 if ((old_chandler = signal (csig, SIG_IGN)) == SIG_ERR)
1bbd0b84 430 SCM_SYSERROR;
e1a191a8 431 if (signal (csig, old_chandler) == SIG_ERR)
1bbd0b84 432 SCM_SYSERROR;
e1a191a8
GH
433 }
434 else
435 {
436 if ((old_chandler = signal (csig, chandler)) == SIG_ERR)
1bbd0b84 437 SCM_SYSERROR;
e1a191a8
GH
438 if (save_handler)
439 orig_handlers[csig] = old_chandler;
440 }
441 if (old_chandler == SIG_DFL || old_chandler == SIG_IGN)
b9bd8526 442 old_handler = scm_from_long ((long) old_chandler);
9de87eea 443 SCM_CRITICAL_SECTION_END;
e11e83f3 444 return scm_cons (old_handler, scm_from_int (0));
0f2d19dd 445#endif
e1a191a8 446}
1bbd0b84 447#undef FUNC_NAME
e1a191a8 448
adb2c53b 449SCM_DEFINE (scm_restore_signals, "restore-signals", 0, 0, 0,
1bbd0b84 450 (void),
b380b885
MD
451 "Return all signal handlers to the values they had before any call to\n"
452 "@code{sigaction} was made. The return value is unspecified.")
1bbd0b84 453#define FUNC_NAME s_scm_restore_signals
e1a191a8
GH
454{
455 int i;
e1a191a8
GH
456 for (i = 0; i < NSIG; i++)
457 {
458#ifdef HAVE_SIGACTION
459 if (orig_handlers[i].sa_handler != SIG_ERR)
460 {
461 if (sigaction (i, &orig_handlers[i], NULL) == -1)
1bbd0b84 462 SCM_SYSERROR;
e1a191a8 463 orig_handlers[i].sa_handler = SIG_ERR;
4057a3e0 464 SCM_SIMPLE_VECTOR_SET (*signal_handlers, i, SCM_BOOL_F);
e1a191a8
GH
465 }
466#else
467 if (orig_handlers[i] != SIG_ERR)
468 {
469 if (signal (i, orig_handlers[i]) == SIG_ERR)
1bbd0b84 470 SCM_SYSERROR;
e1a191a8 471 orig_handlers[i] = SIG_ERR;
4057a3e0 472 SCM_SIMPLE_VECTOR_SET (*signal_handlers, i, SCM_BOOL_F);
e1a191a8
GH
473 }
474#endif
475 }
476 return SCM_UNSPECIFIED;
477}
1bbd0b84 478#undef FUNC_NAME
0f2d19dd 479
adb2c53b 480SCM_DEFINE (scm_alarm, "alarm", 1, 0, 0,
1bbd0b84 481 (SCM i),
b380b885
MD
482 "Set a timer to raise a @code{SIGALRM} signal after the specified\n"
483 "number of seconds (an integer). It's advisable to install a signal\n"
484 "handler for\n"
485 "@code{SIGALRM} beforehand, since the default action is to terminate\n"
486 "the process.\n\n"
487 "The return value indicates the time remaining for the previous alarm,\n"
488 "if any. The new value replaces the previous alarm. If there was\n"
489 "no previous alarm, the return value is zero.")
1bbd0b84 490#define FUNC_NAME s_scm_alarm
0f2d19dd 491{
a55c2b68 492 return scm_from_uint (alarm (scm_to_uint (i)));
0f2d19dd 493}
1bbd0b84 494#undef FUNC_NAME
0f2d19dd 495
53f8a0d2
RB
496#ifdef HAVE_SETITIMER
497SCM_DEFINE (scm_setitimer, "setitimer", 5, 0, 0,
498 (SCM which_timer,
499 SCM interval_seconds, SCM interval_microseconds,
500 SCM value_seconds, SCM value_microseconds),
501 "Set the timer specified by @var{which_timer} according to the given\n"
502 "@var{interval_seconds}, @var{interval_microseconds},\n"
503 "@var{value_seconds}, and @var{value_microseconds} values.\n"
504 "\n"
505 "Return information about the timer's previous setting."
506 "\n"
507 "Errors are handled as described in the guile info pages under ``POSIX\n"
508 "Interface Conventions''.\n"
509 "\n"
9401323e 510 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
53f8a0d2
RB
511 "and @code{ITIMER_PROF}.\n"
512 "\n"
513 "The return value will be a list of two cons pairs representing the\n"
514 "current state of the given timer. The first pair is the seconds and\n"
515 "microseconds of the timer @code{it_interval}, and the second pair is\n"
9401323e 516 "the seconds and microseconds of the timer @code{it_value}.")
53f8a0d2
RB
517#define FUNC_NAME s_scm_setitimer
518{
519 int rv;
520 int c_which_timer;
521 struct itimerval new_timer;
522 struct itimerval old_timer;
523
524 c_which_timer = SCM_NUM2INT(1, which_timer);
525 new_timer.it_interval.tv_sec = SCM_NUM2LONG(2, interval_seconds);
526 new_timer.it_interval.tv_usec = SCM_NUM2LONG(3, interval_microseconds);
527 new_timer.it_value.tv_sec = SCM_NUM2LONG(4, value_seconds);
528 new_timer.it_value.tv_usec = SCM_NUM2LONG(5, value_microseconds);
529
530 SCM_SYSCALL(rv = setitimer(c_which_timer, &new_timer, &old_timer));
531
532 if(rv != 0)
533 SCM_SYSERROR;
534
b9bd8526
MV
535 return scm_list_2 (scm_cons (scm_from_long (old_timer.it_interval.tv_sec),
536 scm_from_long (old_timer.it_interval.tv_usec)),
537 scm_cons (scm_from_long (old_timer.it_value.tv_sec),
538 scm_from_long (old_timer.it_value.tv_usec)));
53f8a0d2
RB
539}
540#undef FUNC_NAME
541#endif /* HAVE_SETITIMER */
542
543#ifdef HAVE_GETITIMER
544SCM_DEFINE (scm_getitimer, "getitimer", 1, 0, 0,
545 (SCM which_timer),
546 "Return information about the timer specified by @var{which_timer}"
547 "\n"
548 "Errors are handled as described in the guile info pages under ``POSIX\n"
549 "Interface Conventions''.\n"
550 "\n"
9401323e 551 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
53f8a0d2
RB
552 "and @code{ITIMER_PROF}.\n"
553 "\n"
554 "The return value will be a list of two cons pairs representing the\n"
555 "current state of the given timer. The first pair is the seconds and\n"
556 "microseconds of the timer @code{it_interval}, and the second pair is\n"
9401323e 557 "the seconds and microseconds of the timer @code{it_value}.")
53f8a0d2
RB
558#define FUNC_NAME s_scm_getitimer
559{
560 int rv;
561 int c_which_timer;
562 struct itimerval old_timer;
563
564 c_which_timer = SCM_NUM2INT(1, which_timer);
565
566 SCM_SYSCALL(rv = getitimer(c_which_timer, &old_timer));
567
568 if(rv != 0)
569 SCM_SYSERROR;
570
b9bd8526
MV
571 return scm_list_2 (scm_cons (scm_from_long (old_timer.it_interval.tv_sec),
572 scm_from_long (old_timer.it_interval.tv_usec)),
573 scm_cons (scm_from_long (old_timer.it_value.tv_sec),
574 scm_from_long (old_timer.it_value.tv_usec)));
53f8a0d2
RB
575}
576#undef FUNC_NAME
577#endif /* HAVE_GETITIMER */
578
0e958795 579#ifdef HAVE_PAUSE
adb2c53b 580SCM_DEFINE (scm_pause, "pause", 0, 0, 0,
1bbd0b84 581 (),
b380b885
MD
582 "Pause the current process (thread?) until a signal arrives whose\n"
583 "action is to either terminate the current process or invoke a\n"
584 "handler procedure. The return value is unspecified.")
1bbd0b84 585#define FUNC_NAME s_scm_pause
0f2d19dd
JB
586{
587 pause ();
588 return SCM_UNSPECIFIED;
589}
1bbd0b84 590#undef FUNC_NAME
0e958795 591#endif
0f2d19dd 592
adb2c53b 593SCM_DEFINE (scm_sleep, "sleep", 1, 0, 0,
1bbd0b84 594 (SCM i),
b380b885
MD
595 "Wait for the given number of seconds (an integer) or until a signal\n"
596 "arrives. The return value is zero if the time elapses or the number\n"
597 "of seconds remaining otherwise.")
1bbd0b84 598#define FUNC_NAME s_scm_sleep
0f2d19dd 599{
9de87eea 600 return scm_from_uint (scm_std_sleep (scm_to_uint (i)));
0f2d19dd 601}
1bbd0b84 602#undef FUNC_NAME
0f2d19dd 603
adb2c53b 604SCM_DEFINE (scm_usleep, "usleep", 1, 0, 0,
1bbd0b84 605 (SCM i),
a55c2b68 606 "Sleep for @var{i} microseconds.")
1bbd0b84 607#define FUNC_NAME s_scm_usleep
ce874f2d 608{
9de87eea 609 return scm_from_ulong (scm_std_usleep (scm_to_ulong (i)));
b74f4728 610}
1bbd0b84 611#undef FUNC_NAME
ce874f2d 612
adb2c53b 613SCM_DEFINE (scm_raise, "raise", 1, 0, 0,
1bbd0b84 614 (SCM sig),
b380b885
MD
615 "Sends a specified signal @var{sig} to the current process, where\n"
616 "@var{sig} is as described for the kill procedure.")
1bbd0b84 617#define FUNC_NAME s_scm_raise
0f2d19dd 618{
a55c2b68 619 if (kill (getpid (), scm_to_int (sig)) != 0)
1bbd0b84 620 SCM_SYSERROR;
e1a191a8 621 return SCM_UNSPECIFIED;
0f2d19dd 622}
1bbd0b84 623#undef FUNC_NAME
0f2d19dd
JB
624
625\f
0f2d19dd 626
e1a191a8
GH
627void
628scm_init_scmsigs ()
0f2d19dd 629{
e1a191a8
GH
630 int i;
631
632 signal_handlers =
86d31dfe
MV
633 SCM_VARIABLE_LOC (scm_c_define ("signal-handlers",
634 scm_c_make_vector (NSIG, SCM_BOOL_F)));
9de87eea 635 signal_handler_asyncs =
dbbaa07c 636 scm_permanent_object (scm_c_make_vector (NSIG, SCM_BOOL_F));
2fbc8609
MV
637 signal_handler_threads =
638 scm_permanent_object (scm_c_make_vector (NSIG, SCM_BOOL_F));
e1a191a8
GH
639
640 for (i = 0; i < NSIG; i++)
641 {
e1a191a8
GH
642#ifdef HAVE_SIGACTION
643 orig_handlers[i].sa_handler = SIG_ERR;
840ae05d 644
e1a191a8
GH
645#else
646 orig_handlers[i] = SIG_ERR;
0f2d19dd 647#endif
840ae05d 648
08b8c694 649#ifdef HAVE_RESTARTABLE_SYSCALLS
7ee92fce 650 /* If HAVE_RESTARTABLE_SYSCALLS is defined, it's important that
adb2c53b 651 signals really are restartable. don't rely on the same
7ee92fce
GH
652 run-time that configure got: reset the default for every signal.
653 */
654#ifdef HAVE_SIGINTERRUPT
655 siginterrupt (i, 0);
de881428 656#elif defined(SA_RESTART)
840ae05d
JB
657 {
658 struct sigaction action;
659
660 sigaction (i, NULL, &action);
661 if (!(action.sa_flags & SA_RESTART))
662 {
3efb80f2 663 action.sa_flags |= SA_RESTART;
840ae05d
JB
664 sigaction (i, &action, NULL);
665 }
666 }
7ee92fce
GH
667#endif
668 /* if neither siginterrupt nor SA_RESTART are available we may
669 as well assume that signals are always restartable. */
840ae05d 670#endif
e1a191a8 671 }
1cc91f1b 672
b9bd8526
MV
673 scm_c_define ("NSIG", scm_from_long (NSIG));
674 scm_c_define ("SIG_IGN", scm_from_long ((long) SIG_IGN));
675 scm_c_define ("SIG_DFL", scm_from_long ((long) SIG_DFL));
e1a191a8 676#ifdef SA_NOCLDSTOP
b9bd8526 677 scm_c_define ("SA_NOCLDSTOP", scm_from_long (SA_NOCLDSTOP));
0f2d19dd 678#endif
e1a191a8 679#ifdef SA_RESTART
b9bd8526 680 scm_c_define ("SA_RESTART", scm_from_long (SA_RESTART));
0f2d19dd 681#endif
1cc91f1b 682
53f8a0d2
RB
683#if defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER)
684 /* Stuff needed by setitimer and getitimer. */
e11e83f3
MV
685 scm_c_define ("ITIMER_REAL", scm_from_int (ITIMER_REAL));
686 scm_c_define ("ITIMER_VIRTUAL", scm_from_int (ITIMER_VIRTUAL));
687 scm_c_define ("ITIMER_PROF", scm_from_int (ITIMER_PROF));
53f8a0d2
RB
688#endif /* defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER) */
689
a0599745 690#include "libguile/scmsigs.x"
0f2d19dd
JB
691}
692
89e00824
ML
693
694/*
695 Local Variables:
696 c-file-style: "gnu"
697 End:
698*/