1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004, 2006,
2 * 2007, 2008, 2009, 2011, 2013, 2014 Free Software Foundation, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 #include <fcntl.h> /* for mingw */
33 #include <process.h> /* for mingw */
38 #ifdef HAVE_SYS_TIME_H
42 #include <full-write.h>
44 #include "libguile/_scm.h"
46 #include "libguile/async.h"
47 #include "libguile/eval.h"
48 #include "libguile/root.h"
49 #include "libguile/vectors.h"
50 #include "libguile/threads.h"
52 #include "libguile/validate.h"
53 #include "libguile/scmsigs.h"
58 /* SIGRETTYPE is the type that signal handlers return. See <signal.h> */
61 # define SIGRETTYPE RETSIGTYPE
64 # define SIGRETTYPE void
66 # define SIGRETTYPE int
72 /* take_signal is installed as the C signal handler whenever a Scheme
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.
77 When Guile is built without threads, the signal handler will
78 install the async directly.
82 /* Scheme vectors with information about a signal. signal_handlers
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
86 signal_handler_threads points to the thread that a signal should be
89 static SCM
*signal_handlers
;
90 static SCM signal_handler_asyncs
;
91 static SCM signal_handler_threads
;
93 /* The signal delivery thread. */
94 scm_i_thread
*scm_i_signal_delivery_thread
= NULL
;
96 /* The mutex held when launching the signal delivery thread. */
97 static scm_i_pthread_mutex_t signal_delivery_thread_mutex
=
98 SCM_I_PTHREAD_MUTEX_INITIALIZER
;
101 /* saves the original C handlers, when a new handler is installed.
102 set to SIG_ERR if the original handler is installed. */
103 #ifdef HAVE_SIGACTION
104 static struct sigaction orig_handlers
[NSIG
];
106 static SIGRETTYPE (*orig_handlers
[NSIG
])(int);
110 close_1 (SCM proc
, SCM arg
)
112 return scm_primitive_eval_x (scm_list_3 (scm_sym_lambda
, SCM_EOL
,
113 scm_list_2 (proc
, arg
)));
116 #if SCM_USE_PTHREAD_THREADS
117 /* On mingw there's no notion of inter-process signals, only a raise()
118 within the process itself which apparently invokes the registered handler
119 immediately. Not sure how well the following code will cope in this
120 case. It builds but it may not offer quite the same scheme-level
121 semantics as on a proper system. If you're relying on much in the way of
122 signal handling on mingw you probably lose anyway. */
124 static int signal_pipe
[2];
127 take_signal (int signum
)
129 char sigbyte
= signum
;
130 full_write (signal_pipe
[1], &sigbyte
, 1);
132 #ifndef HAVE_SIGACTION
133 signal (signum
, take_signal
);
137 struct signal_pipe_data
145 read_signal_pipe_data (void * data
)
147 struct signal_pipe_data
*sdata
= data
;
149 sdata
->n
= read (signal_pipe
[0], &sdata
->sigbyte
, 1);
156 signal_delivery_thread (void *data
)
159 #if HAVE_PTHREAD_SIGMASK /* not on mingw, see notes above */
161 sigfillset (&all_sigs
);
162 scm_i_pthread_sigmask (SIG_SETMASK
, &all_sigs
, NULL
);
167 struct signal_pipe_data sigdata
;
169 scm_without_guile (read_signal_pipe_data
, &sigdata
);
171 sig
= sigdata
.sigbyte
;
172 if (sigdata
.n
== 1 && sig
>= 0 && sig
< NSIG
)
176 h
= SCM_SIMPLE_VECTOR_REF (signal_handler_asyncs
, sig
);
177 t
= SCM_SIMPLE_VECTOR_REF (signal_handler_threads
, sig
);
179 scm_system_async_mark_for_thread (h
, t
);
181 else if (sigdata
.n
== 0)
182 break; /* the signal pipe was closed. */
183 else if (sigdata
.n
< 0 && sigdata
.err
!= EINTR
)
184 perror ("error in signal delivery thread");
187 return SCM_UNSPECIFIED
; /* not reached unless all other threads exited */
191 start_signal_delivery_thread (void)
195 scm_i_pthread_mutex_lock (&signal_delivery_thread_mutex
);
197 if (pipe2 (signal_pipe
, O_CLOEXEC
) != 0)
199 signal_thread
= scm_spawn_thread (signal_delivery_thread
, NULL
,
200 scm_handle_by_message
,
201 "signal delivery thread");
202 scm_i_signal_delivery_thread
= SCM_I_THREAD_DATA (signal_thread
);
204 scm_i_pthread_mutex_unlock (&signal_delivery_thread_mutex
);
208 scm_i_ensure_signal_delivery_thread ()
210 static scm_i_pthread_once_t once
= SCM_I_PTHREAD_ONCE_INIT
;
211 scm_i_pthread_once (&once
, start_signal_delivery_thread
);
214 #else /* !SCM_USE_PTHREAD_THREADS */
217 take_signal (int signum
)
219 SCM cell
= SCM_SIMPLE_VECTOR_REF (signal_handler_asyncs
, signum
);
220 scm_i_thread
*t
= SCM_I_CURRENT_THREAD
;
222 if (scm_is_false (SCM_CDR (cell
)))
224 SCM_SETCDR (cell
, t
->active_asyncs
);
225 t
->active_asyncs
= cell
;
226 t
->pending_asyncs
= 1;
229 #ifndef HAVE_SIGACTION
230 signal (signum
, take_signal
);
235 scm_i_ensure_signal_delivery_thread ()
240 #endif /* !SCM_USE_PTHREAD_THREADS */
243 install_handler (int signum
, SCM thread
, SCM handler
)
245 if (scm_is_false (handler
))
247 SCM_SIMPLE_VECTOR_SET (*signal_handlers
, signum
, SCM_BOOL_F
);
248 SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs
, signum
, SCM_BOOL_F
);
252 SCM async
= close_1 (handler
, scm_from_int (signum
));
253 #if !SCM_USE_PTHREAD_THREADS
254 async
= scm_cons (async
, SCM_BOOL_F
);
256 SCM_SIMPLE_VECTOR_SET (*signal_handlers
, signum
, handler
);
257 SCM_SIMPLE_VECTOR_SET (signal_handler_asyncs
, signum
, async
);
260 SCM_SIMPLE_VECTOR_SET (signal_handler_threads
, signum
, thread
);
264 scm_sigaction (SCM signum
, SCM handler
, SCM flags
)
266 return scm_sigaction_for_thread (signum
, handler
, flags
, SCM_UNDEFINED
);
269 /* user interface for installation of signal handlers. */
270 SCM_DEFINE (scm_sigaction_for_thread
, "sigaction", 1, 3, 0,
271 (SCM signum
, SCM handler
, SCM flags
, SCM thread
),
272 "Install or report the signal handler for a specified signal.\n\n"
273 "@var{signum} is the signal number, which can be specified using the value\n"
274 "of variables such as @code{SIGINT}.\n\n"
275 "If @var{handler} is omitted, @code{sigaction} returns a pair: the\n"
276 "CAR is the current\n"
277 "signal hander, which will be either an integer with the value @code{SIG_DFL}\n"
278 "(default action) or @code{SIG_IGN} (ignore), or the Scheme procedure which\n"
279 "handles the signal, or @code{#f} if a non-Scheme procedure handles the\n"
280 "signal. The CDR contains the current @code{sigaction} flags for the handler.\n\n"
281 "If @var{handler} is provided, it is installed as the new handler for\n"
282 "@var{signum}. @var{handler} can be a Scheme procedure taking one\n"
283 "argument, or the value of @code{SIG_DFL} (default action) or\n"
284 "@code{SIG_IGN} (ignore), or @code{#f} to restore whatever signal handler\n"
285 "was installed before @code{sigaction} was first used. When\n"
286 "a scheme procedure has been specified, that procedure will run\n"
287 "in the given @var{thread}. When no thread has been given, the\n"
288 "thread that made this call to @code{sigaction} is used.\n"
289 "Flags can optionally be specified for the new handler.\n"
290 "The return value is a pair with information about the\n"
291 "old handler as described above.\n\n"
292 "This interface does not provide access to the \"signal blocking\"\n"
293 "facility. Maybe this is not needed, since the thread support may\n"
294 "provide solutions to the problem of consistent access to data\n"
296 #define FUNC_NAME s_scm_sigaction_for_thread
299 #ifdef HAVE_SIGACTION
300 struct sigaction action
;
301 struct sigaction old_action
;
303 SIGRETTYPE (* chandler
) (int) = SIG_DFL
;
304 SIGRETTYPE (* old_chandler
) (int);
307 int save_handler
= 0;
311 csig
= scm_to_signed_integer (signum
, 0, NSIG
-1);
313 #if defined(HAVE_SIGACTION)
315 if (!SCM_UNBNDP (flags
))
316 action
.sa_flags
|= scm_to_int (flags
);
317 sigemptyset (&action
.sa_mask
);
320 if (SCM_UNBNDP (thread
))
321 thread
= scm_current_thread ();
324 SCM_VALIDATE_THREAD (4, thread
);
325 if (scm_c_thread_exited_p (thread
))
326 SCM_MISC_ERROR ("thread has already exited", SCM_EOL
);
329 scm_i_ensure_signal_delivery_thread ();
331 SCM_CRITICAL_SECTION_START
;
332 old_handler
= SCM_SIMPLE_VECTOR_REF (*signal_handlers
, csig
);
333 if (SCM_UNBNDP (handler
))
335 else if (scm_is_integer (handler
))
337 long handler_int
= scm_to_long (handler
);
339 if (handler_int
== (long) SIG_DFL
|| handler_int
== (long) SIG_IGN
)
341 #ifdef HAVE_SIGACTION
342 action
.sa_handler
= (SIGRETTYPE (*) (int)) handler_int
;
344 chandler
= (SIGRETTYPE (*) (int)) handler_int
;
346 install_handler (csig
, SCM_BOOL_F
, SCM_BOOL_F
);
350 SCM_CRITICAL_SECTION_END
;
351 SCM_OUT_OF_RANGE (2, handler
);
354 else if (scm_is_false (handler
))
356 /* restore the default handler. */
357 #ifdef HAVE_SIGACTION
358 if (orig_handlers
[csig
].sa_handler
== SIG_ERR
)
362 action
= orig_handlers
[csig
];
363 orig_handlers
[csig
].sa_handler
= SIG_ERR
;
364 install_handler (csig
, SCM_BOOL_F
, SCM_BOOL_F
);
367 if (orig_handlers
[csig
] == SIG_ERR
)
371 chandler
= orig_handlers
[csig
];
372 orig_handlers
[csig
] = SIG_ERR
;
373 install_handler (csig
, SCM_BOOL_F
, SCM_BOOL_F
);
379 SCM_VALIDATE_PROC (2, handler
);
380 #ifdef HAVE_SIGACTION
381 action
.sa_handler
= take_signal
;
382 if (orig_handlers
[csig
].sa_handler
== SIG_ERR
)
385 chandler
= take_signal
;
386 if (orig_handlers
[csig
] == SIG_ERR
)
389 install_handler (csig
, thread
, handler
);
392 /* XXX - Silently ignore setting handlers for `program error signals'
393 because they can't currently be handled by Scheme code.
398 /* This list of program error signals is from the GNU Libc
407 #if defined(SIGIOT) && (SIGIOT != SIGABRT)
422 #ifdef HAVE_SIGACTION
425 if (sigaction (csig
, 0, &old_action
) == -1)
430 if (sigaction (csig
, &action
, &old_action
) == -1)
433 orig_handlers
[csig
] = old_action
;
435 if (old_action
.sa_handler
== SIG_DFL
|| old_action
.sa_handler
== SIG_IGN
)
436 old_handler
= scm_from_long ((long) old_action
.sa_handler
);
437 SCM_CRITICAL_SECTION_END
;
438 return scm_cons (old_handler
, scm_from_int (old_action
.sa_flags
));
442 if ((old_chandler
= signal (csig
, SIG_IGN
)) == SIG_ERR
)
444 if (signal (csig
, old_chandler
) == SIG_ERR
)
449 if ((old_chandler
= signal (csig
, chandler
)) == SIG_ERR
)
452 orig_handlers
[csig
] = old_chandler
;
454 if (old_chandler
== SIG_DFL
|| old_chandler
== SIG_IGN
)
455 old_handler
= scm_from_long ((long) old_chandler
);
456 SCM_CRITICAL_SECTION_END
;
457 return scm_cons (old_handler
, scm_from_int (0));
462 SCM_DEFINE (scm_restore_signals
, "restore-signals", 0, 0, 0,
464 "Return all signal handlers to the values they had before any call to\n"
465 "@code{sigaction} was made. The return value is unspecified.")
466 #define FUNC_NAME s_scm_restore_signals
469 for (i
= 0; i
< NSIG
; i
++)
471 #ifdef HAVE_SIGACTION
472 if (orig_handlers
[i
].sa_handler
!= SIG_ERR
)
474 if (sigaction (i
, &orig_handlers
[i
], NULL
) == -1)
476 orig_handlers
[i
].sa_handler
= SIG_ERR
;
477 SCM_SIMPLE_VECTOR_SET (*signal_handlers
, i
, SCM_BOOL_F
);
480 if (orig_handlers
[i
] != SIG_ERR
)
482 if (signal (i
, orig_handlers
[i
]) == SIG_ERR
)
484 orig_handlers
[i
] = SIG_ERR
;
485 SCM_SIMPLE_VECTOR_SET (*signal_handlers
, i
, SCM_BOOL_F
);
489 return SCM_UNSPECIFIED
;
494 SCM_DEFINE (scm_alarm
, "alarm", 1, 0, 0,
496 "Set a timer to raise a @code{SIGALRM} signal after the specified\n"
497 "number of seconds (an integer). It's advisable to install a signal\n"
499 "@code{SIGALRM} beforehand, since the default action is to terminate\n"
501 "The return value indicates the time remaining for the previous alarm,\n"
502 "if any. The new value replaces the previous alarm. If there was\n"
503 "no previous alarm, the return value is zero.")
504 #define FUNC_NAME s_scm_alarm
506 return scm_from_uint (alarm (scm_to_uint (i
)));
509 #endif /* HAVE_ALARM */
511 #ifdef HAVE_SETITIMER
512 SCM_DEFINE (scm_setitimer
, "setitimer", 5, 0, 0,
514 SCM interval_seconds
, SCM interval_microseconds
,
515 SCM value_seconds
, SCM value_microseconds
),
516 "Set the timer specified by @var{which_timer} according to the given\n"
517 "@var{interval_seconds}, @var{interval_microseconds},\n"
518 "@var{value_seconds}, and @var{value_microseconds} values.\n"
520 "Return information about the timer's previous setting."
522 "Errors are handled as described in the guile info pages under ``POSIX\n"
523 "Interface Conventions''.\n"
525 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
526 "and @code{ITIMER_PROF}.\n"
528 "The return value will be a list of two cons pairs representing the\n"
529 "current state of the given timer. The first pair is the seconds and\n"
530 "microseconds of the timer @code{it_interval}, and the second pair is\n"
531 "the seconds and microseconds of the timer @code{it_value}.")
532 #define FUNC_NAME s_scm_setitimer
536 struct itimerval new_timer
;
537 struct itimerval old_timer
;
539 c_which_timer
= SCM_NUM2INT(1, which_timer
);
540 new_timer
.it_interval
.tv_sec
= SCM_NUM2LONG(2, interval_seconds
);
541 new_timer
.it_interval
.tv_usec
= SCM_NUM2LONG(3, interval_microseconds
);
542 new_timer
.it_value
.tv_sec
= SCM_NUM2LONG(4, value_seconds
);
543 new_timer
.it_value
.tv_usec
= SCM_NUM2LONG(5, value_microseconds
);
545 SCM_SYSCALL(rv
= setitimer(c_which_timer
, &new_timer
, &old_timer
));
550 return scm_list_2 (scm_cons (scm_from_long (old_timer
.it_interval
.tv_sec
),
551 scm_from_long (old_timer
.it_interval
.tv_usec
)),
552 scm_cons (scm_from_long (old_timer
.it_value
.tv_sec
),
553 scm_from_long (old_timer
.it_value
.tv_usec
)));
556 #endif /* HAVE_SETITIMER */
558 #ifdef HAVE_GETITIMER
559 SCM_DEFINE (scm_getitimer
, "getitimer", 1, 0, 0,
561 "Return information about the timer specified by @var{which_timer}"
563 "Errors are handled as described in the guile info pages under ``POSIX\n"
564 "Interface Conventions''.\n"
566 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
567 "and @code{ITIMER_PROF}.\n"
569 "The return value will be a list of two cons pairs representing the\n"
570 "current state of the given timer. The first pair is the seconds and\n"
571 "microseconds of the timer @code{it_interval}, and the second pair is\n"
572 "the seconds and microseconds of the timer @code{it_value}.")
573 #define FUNC_NAME s_scm_getitimer
577 struct itimerval old_timer
;
579 c_which_timer
= SCM_NUM2INT(1, which_timer
);
581 SCM_SYSCALL(rv
= getitimer(c_which_timer
, &old_timer
));
586 return scm_list_2 (scm_cons (scm_from_long (old_timer
.it_interval
.tv_sec
),
587 scm_from_long (old_timer
.it_interval
.tv_usec
)),
588 scm_cons (scm_from_long (old_timer
.it_value
.tv_sec
),
589 scm_from_long (old_timer
.it_value
.tv_usec
)));
592 #endif /* HAVE_GETITIMER */
595 SCM_DEFINE (scm_pause
, "pause", 0, 0, 0,
597 "Pause the current process (thread?) until a signal arrives whose\n"
598 "action is to either terminate the current process or invoke a\n"
599 "handler procedure. The return value is unspecified.")
600 #define FUNC_NAME s_scm_pause
603 return SCM_UNSPECIFIED
;
608 SCM_DEFINE (scm_sleep
, "sleep", 1, 0, 0,
610 "Wait for the given number of seconds (an integer) or until a signal\n"
611 "arrives. The return value is zero if the time elapses or the number\n"
612 "of seconds remaining otherwise.\n"
614 "See also @code{usleep}.")
615 #define FUNC_NAME s_scm_sleep
617 return scm_from_uint (scm_std_sleep (scm_to_uint (i
)));
621 SCM_DEFINE (scm_usleep
, "usleep", 1, 0, 0,
623 "Wait the given period @var{usecs} microseconds (an integer).\n"
624 "If a signal arrives the wait stops and the return value is the\n"
625 "time remaining, in microseconds. If the period elapses with no\n"
626 "signal the return is zero.\n"
628 "On most systems the process scheduler is not microsecond accurate and\n"
629 "the actual period slept by @code{usleep} may be rounded to a system\n"
630 "clock tick boundary. Traditionally such ticks were 10 milliseconds\n"
631 "apart, and that interval is often still used.\n"
633 "See also @code{sleep}.")
634 #define FUNC_NAME s_scm_usleep
636 return scm_from_ulong (scm_std_usleep (scm_to_ulong (i
)));
640 SCM_DEFINE (scm_raise
, "raise", 1, 0, 0,
642 "Sends a specified signal @var{sig} to the current process, where\n"
643 "@var{sig} is as described for the kill procedure.")
644 #define FUNC_NAME s_scm_raise
646 if (raise (scm_to_int (sig
)) != 0)
648 return SCM_UNSPECIFIED
;
655 scm_i_close_signal_pipe()
657 /* SIGNAL_DELIVERY_THREAD_MUTEX is only locked while the signal delivery
658 thread is being launched. The thread that calls this function is
659 already holding the thread admin mutex, so if the delivery thread hasn't
660 been launched at this point, it never will be before shutdown. */
661 scm_i_pthread_mutex_lock (&signal_delivery_thread_mutex
);
663 #if SCM_USE_PTHREAD_THREADS
664 if (scm_i_signal_delivery_thread
!= NULL
)
665 close (signal_pipe
[1]);
668 scm_i_pthread_mutex_unlock (&signal_delivery_thread_mutex
);
677 SCM_VARIABLE_LOC (scm_c_define ("signal-handlers",
678 scm_c_make_vector (NSIG
, SCM_BOOL_F
)));
679 signal_handler_asyncs
= scm_c_make_vector (NSIG
, SCM_BOOL_F
);
680 signal_handler_threads
= scm_c_make_vector (NSIG
, SCM_BOOL_F
);
682 for (i
= 0; i
< NSIG
; i
++)
684 #ifdef HAVE_SIGACTION
685 orig_handlers
[i
].sa_handler
= SIG_ERR
;
688 orig_handlers
[i
] = SIG_ERR
;
692 scm_c_define ("NSIG", scm_from_long (NSIG
));
693 scm_c_define ("SIG_IGN", scm_from_long ((long) SIG_IGN
));
694 scm_c_define ("SIG_DFL", scm_from_long ((long) SIG_DFL
));
696 scm_c_define ("SA_NOCLDSTOP", scm_from_long (SA_NOCLDSTOP
));
699 scm_c_define ("SA_RESTART", scm_from_long (SA_RESTART
));
702 #if defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER)
703 /* Stuff needed by setitimer and getitimer. */
704 scm_c_define ("ITIMER_REAL", scm_from_int (ITIMER_REAL
));
705 scm_c_define ("ITIMER_VIRTUAL", scm_from_int (ITIMER_VIRTUAL
));
706 scm_c_define ("ITIMER_PROF", scm_from_int (ITIMER_PROF
));
707 #endif /* defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER) */
709 #include "libguile/scmsigs.x"