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