1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
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., 51 Franklin Street, Fifth Floor, Boston, MA
26 #include <fcntl.h> /* for mingw */
31 #include "libguile/_scm.h"
33 #include "libguile/async.h"
34 #include "libguile/eval.h"
35 #include "libguile/root.h"
36 #include "libguile/vectors.h"
37 #include "libguile/threads.h"
39 #include "libguile/validate.h"
40 #include "libguile/scmsigs.h"
43 #include <io.h> /* for mingw _pipe() */
47 #include <process.h> /* for mingw */
54 #ifdef HAVE_SYS_TIME_H
60 #define alarm(sec) (0)
61 /* This weird comma expression is because Sleep is void under Windows. */
62 #define sleep(sec) (Sleep ((sec) * 1000), 0)
63 #define usleep(usec) (Sleep ((usec) / 1000), 0)
64 #define pipe(fd) _pipe (fd, 256, O_BINARY)
67 #include <full-write.h>
72 /* SIGRETTYPE is the type that signal handlers return. See <signal.h> */
75 # define SIGRETTYPE RETSIGTYPE
78 # define SIGRETTYPE void
80 # define SIGRETTYPE int
86 /* take_signal is installed as the C signal handler whenever a Scheme
87 handler is set. When a signal arrives, take_signal will write a
88 byte into the 'signal pipe'. The 'signal delivery thread' will
89 read this pipe and queue the appropriate asyncs.
91 When Guile is built without threads, the signal handler will
92 install the async directly.
96 /* Scheme vectors with information about a signal. signal_handlers
97 contains the handler procedure or #f, signal_handler_asyncs
98 contains the thunk to be marked as an async when the signal arrives
99 (or the cell with the thunk in a singlethreaded Guile), and
100 signal_handler_threads points to the thread that a signal should be
103 static SCM
*signal_handlers
;
104 static SCM signal_handler_asyncs
;
105 static SCM signal_handler_threads
;
107 /* The signal delivery thread. */
108 scm_i_thread
*scm_i_signal_delivery_thread
= NULL
;
110 /* The mutex held when launching the signal delivery thread. */
111 static scm_i_pthread_mutex_t signal_delivery_thread_mutex
=
112 SCM_I_PTHREAD_MUTEX_INITIALIZER
;
115 /* saves the original C handlers, when a new handler is installed.
116 set to SIG_ERR if the original handler is installed. */
117 #ifdef HAVE_SIGACTION
118 static struct sigaction orig_handlers
[NSIG
];
120 static SIGRETTYPE (*orig_handlers
[NSIG
])(int);
124 close_1 (SCM proc
, SCM arg
)
126 return scm_primitive_eval_x (scm_list_3 (scm_sym_lambda
, SCM_EOL
,
127 scm_list_2 (proc
, arg
)));
130 #if SCM_USE_PTHREAD_THREADS
131 /* On mingw there's no notion of inter-process signals, only a raise()
132 within the process itself which apparently invokes the registered handler
133 immediately. Not sure how well the following code will cope in this
134 case. It builds but it may not offer quite the same scheme-level
135 semantics as on a proper system. If you're relying on much in the way of
136 signal handling on mingw you probably lose anyway. */
138 static int signal_pipe
[2];
141 take_signal (int signum
)
143 char sigbyte
= signum
;
144 full_write (signal_pipe
[1], &sigbyte
, 1);
146 #ifndef HAVE_SIGACTION
147 signal (signum
, take_signal
);
152 signal_delivery_thread (void *data
)
156 #if HAVE_PTHREAD_SIGMASK /* not on mingw, see notes above */
158 sigfillset (&all_sigs
);
159 scm_i_pthread_sigmask (SIG_SETMASK
, &all_sigs
, NULL
);
164 n
= read (signal_pipe
[0], &sigbyte
, 1);
166 if (n
== 1 && sig
>= 0 && sig
< NSIG
)
170 h
= SCM_SIMPLE_VECTOR_REF (signal_handler_asyncs
, sig
);
171 t
= SCM_SIMPLE_VECTOR_REF (signal_handler_threads
, sig
);
173 scm_system_async_mark_for_thread (h
, t
);
176 break; /* the signal pipe was closed. */
177 else if (n
< 0 && errno
!= EINTR
)
178 perror ("error in signal delivery thread");
181 return SCM_UNSPECIFIED
; /* not reached unless all other threads exited */
185 start_signal_delivery_thread (void)
189 scm_i_pthread_mutex_lock (&signal_delivery_thread_mutex
);
191 if (pipe (signal_pipe
) != 0)
193 signal_thread
= scm_spawn_thread (signal_delivery_thread
, NULL
,
194 scm_handle_by_message
,
195 "signal delivery thread");
196 scm_i_signal_delivery_thread
= SCM_I_THREAD_DATA (signal_thread
);
198 scm_i_pthread_mutex_unlock (&signal_delivery_thread_mutex
);
202 scm_i_ensure_signal_delivery_thread ()
204 static scm_i_pthread_once_t once
= SCM_I_PTHREAD_ONCE_INIT
;
205 scm_i_pthread_once (&once
, start_signal_delivery_thread
);
208 #else /* !SCM_USE_PTHREAD_THREADS */
211 take_signal (int signum
)
213 SCM cell
= SCM_SIMPLE_VECTOR_REF (signal_handler_asyncs
, signum
);
214 scm_i_thread
*t
= SCM_I_CURRENT_THREAD
;
216 if (scm_is_false (SCM_CDR (cell
)))
218 SCM_SETCDR (cell
, t
->active_asyncs
);
219 t
->active_asyncs
= cell
;
220 t
->pending_asyncs
= 1;
223 #ifndef HAVE_SIGACTION
224 signal (signum
, take_signal
);
229 scm_i_ensure_signal_delivery_thread ()
234 #endif /* !SCM_USE_PTHREAD_THREADS */
237 install_handler (int signum
, SCM thread
, SCM handler
)
239 if (scm_is_false (handler
))
241 SCM_SIMPLE_VECTOR_SET (*signal_handlers
, signum
, SCM_BOOL_F
);
242 SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs
, signum
, SCM_BOOL_F
);
246 SCM async
= close_1 (handler
, scm_from_int (signum
));
247 #if !SCM_USE_PTHREAD_THREADS
248 async
= scm_cons (async
, SCM_BOOL_F
);
250 SCM_SIMPLE_VECTOR_SET (*signal_handlers
, signum
, handler
);
251 SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs
, signum
, async
);
254 SCM_SIMPLE_VECTOR_SET (signal_handler_threads
, signum
, thread
);
258 scm_sigaction (SCM signum
, SCM handler
, SCM flags
)
260 return scm_sigaction_for_thread (signum
, handler
, flags
, SCM_UNDEFINED
);
263 /* user interface for installation of signal handlers. */
264 SCM_DEFINE (scm_sigaction_for_thread
, "sigaction", 1, 3, 0,
265 (SCM signum
, SCM handler
, SCM flags
, SCM thread
),
266 "Install or report the signal handler for a specified signal.\n\n"
267 "@var{signum} is the signal number, which can be specified using the value\n"
268 "of variables such as @code{SIGINT}.\n\n"
269 "If @var{handler} is omitted, @code{sigaction} returns a pair: the\n"
270 "CAR is the current\n"
271 "signal hander, which will be either an integer with the value @code{SIG_DFL}\n"
272 "(default action) or @code{SIG_IGN} (ignore), or the Scheme procedure which\n"
273 "handles the signal, or @code{#f} if a non-Scheme procedure handles the\n"
274 "signal. The CDR contains the current @code{sigaction} flags for the handler.\n\n"
275 "If @var{handler} is provided, it is installed as the new handler for\n"
276 "@var{signum}. @var{handler} can be a Scheme procedure taking one\n"
277 "argument, or the value of @code{SIG_DFL} (default action) or\n"
278 "@code{SIG_IGN} (ignore), or @code{#f} to restore whatever signal handler\n"
279 "was installed before @code{sigaction} was first used. When\n"
280 "a scheme procedure has been specified, that procedure will run\n"
281 "in the given @var{thread}. When no thread has been given, the\n"
282 "thread that made this call to @code{sigaction} is used.\n"
283 "Flags can optionally be specified for the new handler.\n"
284 "The return value is a pair with information about the\n"
285 "old handler as described above.\n\n"
286 "This interface does not provide access to the \"signal blocking\"\n"
287 "facility. Maybe this is not needed, since the thread support may\n"
288 "provide solutions to the problem of consistent access to data\n"
290 #define FUNC_NAME s_scm_sigaction_for_thread
293 #ifdef HAVE_SIGACTION
294 struct sigaction action
;
295 struct sigaction old_action
;
297 SIGRETTYPE (* chandler
) (int) = SIG_DFL
;
298 SIGRETTYPE (* old_chandler
) (int);
301 int save_handler
= 0;
305 csig
= scm_to_signed_integer (signum
, 0, NSIG
-1);
307 #if defined(HAVE_SIGACTION)
309 if (!SCM_UNBNDP (flags
))
310 action
.sa_flags
|= scm_to_int (flags
);
311 sigemptyset (&action
.sa_mask
);
314 if (SCM_UNBNDP (thread
))
315 thread
= scm_current_thread ();
318 SCM_VALIDATE_THREAD (4, thread
);
319 if (scm_c_thread_exited_p (thread
))
320 SCM_MISC_ERROR ("thread has already exited", SCM_EOL
);
323 scm_i_ensure_signal_delivery_thread ();
325 SCM_CRITICAL_SECTION_START
;
326 old_handler
= SCM_SIMPLE_VECTOR_REF (*signal_handlers
, csig
);
327 if (SCM_UNBNDP (handler
))
329 else if (scm_is_integer (handler
))
331 long handler_int
= scm_to_long (handler
);
333 if (handler_int
== (long) SIG_DFL
|| handler_int
== (long) SIG_IGN
)
335 #ifdef HAVE_SIGACTION
336 action
.sa_handler
= (SIGRETTYPE (*) (int)) handler_int
;
338 chandler
= (SIGRETTYPE (*) (int)) handler_int
;
340 install_handler (csig
, SCM_BOOL_F
, SCM_BOOL_F
);
344 SCM_CRITICAL_SECTION_END
;
345 SCM_OUT_OF_RANGE (2, handler
);
348 else if (scm_is_false (handler
))
350 /* restore the default handler. */
351 #ifdef HAVE_SIGACTION
352 if (orig_handlers
[csig
].sa_handler
== SIG_ERR
)
356 action
= orig_handlers
[csig
];
357 orig_handlers
[csig
].sa_handler
= SIG_ERR
;
358 install_handler (csig
, SCM_BOOL_F
, SCM_BOOL_F
);
361 if (orig_handlers
[csig
] == SIG_ERR
)
365 chandler
= orig_handlers
[csig
];
366 orig_handlers
[csig
] = SIG_ERR
;
367 install_handler (csig
, SCM_BOOL_F
, SCM_BOOL_F
);
373 SCM_VALIDATE_PROC (2, handler
);
374 #ifdef HAVE_SIGACTION
375 action
.sa_handler
= take_signal
;
376 if (orig_handlers
[csig
].sa_handler
== SIG_ERR
)
379 chandler
= take_signal
;
380 if (orig_handlers
[csig
] == SIG_ERR
)
383 install_handler (csig
, thread
, handler
);
386 /* XXX - Silently ignore setting handlers for `program error signals'
387 because they can't currently be handled by Scheme code.
392 /* This list of program error signals is from the GNU Libc
401 #if defined(SIGIOT) && (SIGIOT != SIGABRT)
416 #ifdef HAVE_SIGACTION
419 if (sigaction (csig
, 0, &old_action
) == -1)
424 if (sigaction (csig
, &action
, &old_action
) == -1)
427 orig_handlers
[csig
] = old_action
;
429 if (old_action
.sa_handler
== SIG_DFL
|| old_action
.sa_handler
== SIG_IGN
)
430 old_handler
= scm_from_long ((long) old_action
.sa_handler
);
431 SCM_CRITICAL_SECTION_END
;
432 return scm_cons (old_handler
, scm_from_int (old_action
.sa_flags
));
436 if ((old_chandler
= signal (csig
, SIG_IGN
)) == SIG_ERR
)
438 if (signal (csig
, old_chandler
) == SIG_ERR
)
443 if ((old_chandler
= signal (csig
, chandler
)) == SIG_ERR
)
446 orig_handlers
[csig
] = old_chandler
;
448 if (old_chandler
== SIG_DFL
|| old_chandler
== SIG_IGN
)
449 old_handler
= scm_from_long ((long) old_chandler
);
450 SCM_CRITICAL_SECTION_END
;
451 return scm_cons (old_handler
, scm_from_int (0));
456 SCM_DEFINE (scm_restore_signals
, "restore-signals", 0, 0, 0,
458 "Return all signal handlers to the values they had before any call to\n"
459 "@code{sigaction} was made. The return value is unspecified.")
460 #define FUNC_NAME s_scm_restore_signals
463 for (i
= 0; i
< NSIG
; i
++)
465 #ifdef HAVE_SIGACTION
466 if (orig_handlers
[i
].sa_handler
!= SIG_ERR
)
468 if (sigaction (i
, &orig_handlers
[i
], NULL
) == -1)
470 orig_handlers
[i
].sa_handler
= SIG_ERR
;
471 SCM_SIMPLE_VECTOR_SET (*signal_handlers
, i
, SCM_BOOL_F
);
474 if (orig_handlers
[i
] != SIG_ERR
)
476 if (signal (i
, orig_handlers
[i
]) == SIG_ERR
)
478 orig_handlers
[i
] = SIG_ERR
;
479 SCM_SIMPLE_VECTOR_SET (*signal_handlers
, i
, SCM_BOOL_F
);
483 return SCM_UNSPECIFIED
;
487 SCM_DEFINE (scm_alarm
, "alarm", 1, 0, 0,
489 "Set a timer to raise a @code{SIGALRM} signal after the specified\n"
490 "number of seconds (an integer). It's advisable to install a signal\n"
492 "@code{SIGALRM} beforehand, since the default action is to terminate\n"
494 "The return value indicates the time remaining for the previous alarm,\n"
495 "if any. The new value replaces the previous alarm. If there was\n"
496 "no previous alarm, the return value is zero.")
497 #define FUNC_NAME s_scm_alarm
499 return scm_from_uint (alarm (scm_to_uint (i
)));
503 #ifdef HAVE_SETITIMER
504 SCM_DEFINE (scm_setitimer
, "setitimer", 5, 0, 0,
506 SCM interval_seconds
, SCM interval_microseconds
,
507 SCM value_seconds
, SCM value_microseconds
),
508 "Set the timer specified by @var{which_timer} according to the given\n"
509 "@var{interval_seconds}, @var{interval_microseconds},\n"
510 "@var{value_seconds}, and @var{value_microseconds} values.\n"
512 "Return information about the timer's previous setting."
514 "Errors are handled as described in the guile info pages under ``POSIX\n"
515 "Interface Conventions''.\n"
517 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
518 "and @code{ITIMER_PROF}.\n"
520 "The return value will be a list of two cons pairs representing the\n"
521 "current state of the given timer. The first pair is the seconds and\n"
522 "microseconds of the timer @code{it_interval}, and the second pair is\n"
523 "the seconds and microseconds of the timer @code{it_value}.")
524 #define FUNC_NAME s_scm_setitimer
528 struct itimerval new_timer
;
529 struct itimerval old_timer
;
531 c_which_timer
= SCM_NUM2INT(1, which_timer
);
532 new_timer
.it_interval
.tv_sec
= SCM_NUM2LONG(2, interval_seconds
);
533 new_timer
.it_interval
.tv_usec
= SCM_NUM2LONG(3, interval_microseconds
);
534 new_timer
.it_value
.tv_sec
= SCM_NUM2LONG(4, value_seconds
);
535 new_timer
.it_value
.tv_usec
= SCM_NUM2LONG(5, value_microseconds
);
537 SCM_SYSCALL(rv
= setitimer(c_which_timer
, &new_timer
, &old_timer
));
542 return scm_list_2 (scm_cons (scm_from_long (old_timer
.it_interval
.tv_sec
),
543 scm_from_long (old_timer
.it_interval
.tv_usec
)),
544 scm_cons (scm_from_long (old_timer
.it_value
.tv_sec
),
545 scm_from_long (old_timer
.it_value
.tv_usec
)));
548 #endif /* HAVE_SETITIMER */
550 #ifdef HAVE_GETITIMER
551 SCM_DEFINE (scm_getitimer
, "getitimer", 1, 0, 0,
553 "Return information about the timer specified by @var{which_timer}"
555 "Errors are handled as described in the guile info pages under ``POSIX\n"
556 "Interface Conventions''.\n"
558 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
559 "and @code{ITIMER_PROF}.\n"
561 "The return value will be a list of two cons pairs representing the\n"
562 "current state of the given timer. The first pair is the seconds and\n"
563 "microseconds of the timer @code{it_interval}, and the second pair is\n"
564 "the seconds and microseconds of the timer @code{it_value}.")
565 #define FUNC_NAME s_scm_getitimer
569 struct itimerval old_timer
;
571 c_which_timer
= SCM_NUM2INT(1, which_timer
);
573 SCM_SYSCALL(rv
= getitimer(c_which_timer
, &old_timer
));
578 return scm_list_2 (scm_cons (scm_from_long (old_timer
.it_interval
.tv_sec
),
579 scm_from_long (old_timer
.it_interval
.tv_usec
)),
580 scm_cons (scm_from_long (old_timer
.it_value
.tv_sec
),
581 scm_from_long (old_timer
.it_value
.tv_usec
)));
584 #endif /* HAVE_GETITIMER */
587 SCM_DEFINE (scm_pause
, "pause", 0, 0, 0,
589 "Pause the current process (thread?) until a signal arrives whose\n"
590 "action is to either terminate the current process or invoke a\n"
591 "handler procedure. The return value is unspecified.")
592 #define FUNC_NAME s_scm_pause
595 return SCM_UNSPECIFIED
;
600 SCM_DEFINE (scm_sleep
, "sleep", 1, 0, 0,
602 "Wait for the given number of seconds (an integer) or until a signal\n"
603 "arrives. The return value is zero if the time elapses or the number\n"
604 "of seconds remaining otherwise.\n"
606 "See also @code{usleep}.")
607 #define FUNC_NAME s_scm_sleep
609 return scm_from_uint (scm_std_sleep (scm_to_uint (i
)));
613 SCM_DEFINE (scm_usleep
, "usleep", 1, 0, 0,
615 "Wait the given period @var{usecs} microseconds (an integer).\n"
616 "If a signal arrives the wait stops and the return value is the\n"
617 "time remaining, in microseconds. If the period elapses with no\n"
618 "signal the return is zero.\n"
620 "On most systems the process scheduler is not microsecond accurate and\n"
621 "the actual period slept by @code{usleep} may be rounded to a system\n"
622 "clock tick boundary. Traditionally such ticks were 10 milliseconds\n"
623 "apart, and that interval is often still used.\n"
625 "See also @code{sleep}.")
626 #define FUNC_NAME s_scm_usleep
628 return scm_from_ulong (scm_std_usleep (scm_to_ulong (i
)));
632 SCM_DEFINE (scm_raise
, "raise", 1, 0, 0,
634 "Sends a specified signal @var{sig} to the current process, where\n"
635 "@var{sig} is as described for the kill procedure.")
636 #define FUNC_NAME s_scm_raise
638 if (raise (scm_to_int (sig
)) != 0)
640 return SCM_UNSPECIFIED
;
647 scm_i_close_signal_pipe()
649 /* SIGNAL_DELIVERY_THREAD_MUTEX is only locked while the signal delivery
650 thread is being launched. The thread that calls this function is
651 already holding the thread admin mutex, so if the delivery thread hasn't
652 been launched at this point, it never will be before shutdown. */
653 scm_i_pthread_mutex_lock (&signal_delivery_thread_mutex
);
655 #if SCM_USE_PTHREAD_THREADS
656 if (scm_i_signal_delivery_thread
!= NULL
)
657 close (signal_pipe
[1]);
660 scm_i_pthread_mutex_unlock (&signal_delivery_thread_mutex
);
669 SCM_VARIABLE_LOC (scm_c_define ("signal-handlers",
670 scm_c_make_vector (NSIG
, SCM_BOOL_F
)));
671 signal_handler_asyncs
= scm_c_make_vector (NSIG
, SCM_BOOL_F
);
672 signal_handler_threads
= scm_c_make_vector (NSIG
, SCM_BOOL_F
);
674 for (i
= 0; i
< NSIG
; i
++)
676 #ifdef HAVE_SIGACTION
677 orig_handlers
[i
].sa_handler
= SIG_ERR
;
680 orig_handlers
[i
] = SIG_ERR
;
684 scm_c_define ("NSIG", scm_from_long (NSIG
));
685 scm_c_define ("SIG_IGN", scm_from_long ((long) SIG_IGN
));
686 scm_c_define ("SIG_DFL", scm_from_long ((long) SIG_DFL
));
688 scm_c_define ("SA_NOCLDSTOP", scm_from_long (SA_NOCLDSTOP
));
691 scm_c_define ("SA_RESTART", scm_from_long (SA_RESTART
));
694 #if defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER)
695 /* Stuff needed by setitimer and getitimer. */
696 scm_c_define ("ITIMER_REAL", scm_from_int (ITIMER_REAL
));
697 scm_c_define ("ITIMER_VIRTUAL", scm_from_int (ITIMER_VIRTUAL
));
698 scm_c_define ("ITIMER_PROF", scm_from_int (ITIMER_PROF
));
699 #endif /* defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER) */
701 #include "libguile/scmsigs.x"