1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
52 #include "libguile/_scm.h"
54 #include "libguile/async.h"
55 #include "libguile/eval.h"
56 #include "libguile/root.h"
57 #include "libguile/vectors.h"
59 #include "libguile/validate.h"
60 #include "libguile/scmsigs.h"
66 #ifdef HAVE_SYS_TIME_H
72 #define alarm(sec) (0)
73 /* This weird comma expression is because Sleep is void under Windows. */
74 #define sleep(sec) (Sleep ((sec) * 1000), 0)
75 #define usleep(usec) (Sleep ((usec) / 1000), 0)
76 #define kill(pid, sig) raise (sig)
81 /* SIGRETTYPE is the type that signal handlers return. See <signal.h> */
84 # define SIGRETTYPE RETSIGTYPE
87 # define SIGRETTYPE void
89 # define SIGRETTYPE int
95 /* take_signal is installed as the C signal handler whenever a Scheme
96 handler is set. when a signal arrives, take_signal will queue the
97 Scheme handler procedure for its thread. */
100 /* Scheme vectors with information about a signal. signal_handlers
101 contains the handler procedure or #f, signal_handler_cells contains
102 pre-queued cells for the handler (since we can't do fancy things
103 during signal delivery), signal_cell_handlers contains the SCM
104 value to be stuffed into the pre-queued cell upon delivery, and
105 signal_handler_threads points to the thread that a signal should be
108 static SCM
*signal_handlers
;
109 static SCM signal_handler_cells
;
110 static SCM signal_cell_handlers
;
111 static SCM signal_handler_threads
;
113 /* saves the original C handlers, when a new handler is installed.
114 set to SIG_ERR if the original handler is installed. */
115 #ifdef HAVE_SIGACTION
116 static struct sigaction orig_handlers
[NSIG
];
118 static SIGRETTYPE (*orig_handlers
[NSIG
])(int);
123 take_signal (int signum
)
125 if (signum
>= 0 && signum
< NSIG
)
127 SCM cell
= SCM_VECTOR_REF(signal_handler_cells
, signum
);
128 SCM handler
= SCM_VECTOR_REF(signal_cell_handlers
, signum
);
129 SCM thread
= SCM_VECTOR_REF(signal_handler_threads
, signum
);
130 scm_root_state
*root
= scm_i_thread_root (thread
);
131 if (SCM_CONSP (cell
))
133 SCM_SETCAR (cell
, handler
);
134 root
->pending_asyncs
= 1;
138 #ifndef HAVE_SIGACTION
139 signal (signum
, take_signal
);
144 scm_sigaction (SCM signum
, SCM handler
, SCM flags
)
146 return scm_sigaction_for_thread (signum
, handler
, flags
, SCM_UNDEFINED
);
150 close_1 (SCM proc
, SCM arg
)
152 return scm_primitive_eval_x (scm_list_3 (scm_sym_lambda
, SCM_EOL
,
153 scm_list_2 (proc
, arg
)));
156 /* Make sure that signal SIGNUM can be delivered to THREAD, using
157 HANDLER. THREAD and HANDLER must either both be non-#f (which
158 means install the handler), or both #f (which means deinstall an
162 struct install_handler_data
{
169 scm_delq_spine_x (SCM cell
, SCM list
)
171 SCM s
= list
, prev
= SCM_BOOL_F
;
173 while (!SCM_EQ_P (cell
, s
))
180 if (SCM_FALSEP (prev
))
181 return SCM_CDR (cell
);
184 SCM_SETCDR (prev
, SCM_CDR (cell
));
190 really_install_handler (void *data
)
192 struct install_handler_data
*args
= data
;
193 int signum
= args
->signum
;
194 SCM thread
= args
->thread
;
195 SCM handler
= args
->handler
;
199 /* The following modifications are done while signals can be
200 delivered. That is not a real problem since the signal handler
201 will only touch the car of the handler cell and set the
202 pending_asyncs trigger of a thread. While the data structures
203 are in flux, the signal handler might store the wrong handler in
204 the cell, or set pending_asyncs of the wrong thread. We fix this
205 at the end by making sure that the cell has the right handler in
206 it, if any, and that pending_asyncs is set for the new thread.
209 /* Make sure we have a cell. */
210 cell
= SCM_VECTOR_REF (signal_handler_cells
, signum
);
211 if (SCM_FALSEP (cell
))
213 cell
= scm_cons (SCM_BOOL_F
, SCM_EOL
);
214 SCM_VECTOR_SET (signal_handler_cells
, signum
, cell
);
217 /* Make sure it is queued for the right thread. */
218 old_thread
= SCM_VECTOR_REF (signal_handler_threads
, signum
);
219 if (!SCM_EQ_P (thread
, old_thread
))
222 if (!SCM_FALSEP (old_thread
))
224 r
= scm_i_thread_root (old_thread
);
225 r
->signal_asyncs
= scm_delq_spine_x (cell
, r
->signal_asyncs
);
227 if (!SCM_FALSEP (thread
))
229 r
= scm_i_thread_root (thread
);
230 SCM_SETCDR (cell
, r
->signal_asyncs
);
231 r
->signal_asyncs
= cell
;
232 /* Set pending_asyncs just in case. A signal that is
233 delivered while we modify the data structures here might set
234 pending_asyncs of old_thread. */
235 r
->pending_asyncs
= 1;
237 SCM_VECTOR_SET (signal_handler_threads
, signum
, thread
);
240 /* Set the new handler. */
241 if (SCM_FALSEP (handler
))
243 SCM_VECTOR_SET (*signal_handlers
, signum
, SCM_BOOL_F
);
244 SCM_VECTOR_SET (signal_cell_handlers
, signum
, SCM_BOOL_F
);
248 SCM_VECTOR_SET (*signal_handlers
, signum
, handler
);
249 SCM_VECTOR_SET (signal_cell_handlers
, signum
,
250 close_1 (handler
, scm_int2num (signum
)));
253 /* Now fix up the cell. It might contain the old handler but since
254 it is now queued for the new thread, we must make sure that the
255 new handler is run. Any signal that is delivered during the
256 following code will install the new handler, so we have no
259 if (!SCM_FALSEP (SCM_CAR (cell
)))
260 SCM_SETCAR (cell
, SCM_VECTOR_REF (signal_cell_handlers
, signum
));
262 /* Phfew. That should be it. */
267 install_handler (int signum
, SCM thread
, SCM handler
)
269 /* We block asyncs while installing the handler. It would be safe
270 to leave them on, but we might run the wrong handler should a
274 struct install_handler_data args
;
275 args
.signum
= signum
;
276 args
.thread
= thread
;
277 args
.handler
= handler
;
278 scm_c_call_with_blocked_asyncs (really_install_handler
, &args
);
281 /* user interface for installation of signal handlers. */
282 SCM_DEFINE (scm_sigaction_for_thread
, "sigaction", 1, 3, 0,
283 (SCM signum
, SCM handler
, SCM flags
, SCM thread
),
284 "Install or report the signal handler for a specified signal.\n\n"
285 "@var{signum} is the signal number, which can be specified using the value\n"
286 "of variables such as @code{SIGINT}.\n\n"
287 "If @var{handler} is omitted, @code{sigaction} returns a pair: the\n"
288 "CAR is the current\n"
289 "signal hander, which will be either an integer with the value @code{SIG_DFL}\n"
290 "(default action) or @code{SIG_IGN} (ignore), or the Scheme procedure which\n"
291 "handles the signal, or @code{#f} if a non-Scheme procedure handles the\n"
292 "signal. The CDR contains the current @code{sigaction} flags for the handler.\n\n"
293 "If @var{handler} is provided, it is installed as the new handler for\n"
294 "@var{signum}. @var{handler} can be a Scheme procedure taking one\n"
295 "argument, or the value of @code{SIG_DFL} (default action) or\n"
296 "@code{SIG_IGN} (ignore), or @code{#f} to restore whatever signal handler\n"
297 "was installed before @code{sigaction} was first used. When\n"
298 "a scheme procedure has been specified, that procedure will run\n"
299 "in the given @var{thread}. When no thread has been given, the\n"
300 "thread that made this call to @code{sigaction} is used.\n"
302 "optionally be specified for the new handler (@code{SA_RESTART} will\n"
303 "always be added if it's available and the system is using restartable\n"
304 "system calls.) The return value is a pair with information about the\n"
305 "old handler as described above.\n\n"
306 "This interface does not provide access to the \"signal blocking\"\n"
307 "facility. Maybe this is not needed, since the thread support may\n"
308 "provide solutions to the problem of consistent access to data\n"
310 #define FUNC_NAME s_scm_sigaction_for_thread
313 #ifdef HAVE_SIGACTION
314 struct sigaction action
;
315 struct sigaction old_action
;
317 SIGRETTYPE (* chandler
) (int) = SIG_DFL
;
318 SIGRETTYPE (* old_chandler
) (int);
321 int save_handler
= 0;
325 SCM_VALIDATE_INUM_COPY (1, signum
, csig
);
326 if (csig
< 0 || csig
> NSIG
)
327 SCM_OUT_OF_RANGE (1, signum
);
328 #if defined(HAVE_SIGACTION)
329 #if defined(SA_RESTART) && defined(HAVE_RESTARTABLE_SYSCALLS)
330 /* don't allow SA_RESTART to be omitted if HAVE_RESTARTABLE_SYSCALLS
331 is defined, since libguile would be likely to produce spurious
333 action
.sa_flags
= SA_RESTART
;
337 if (!SCM_UNBNDP (flags
))
339 SCM_VALIDATE_INUM (3, flags
);
340 action
.sa_flags
|= SCM_INUM (flags
);
342 sigemptyset (&action
.sa_mask
);
345 if (SCM_UNBNDP (thread
))
346 thread
= scm_current_thread ();
349 SCM_VALIDATE_THREAD (4, thread
);
350 if (scm_c_thread_exited_p (thread
))
351 SCM_MISC_ERROR ("thread has already exited", SCM_EOL
);
355 old_handler
= SCM_VECTOR_REF(*signal_handlers
, csig
);
356 if (SCM_UNBNDP (handler
))
358 else if (SCM_EQ_P (scm_integer_p (handler
), SCM_BOOL_T
))
360 if (SCM_NUM2LONG (2, handler
) == (long) SIG_DFL
361 || SCM_NUM2LONG (2, handler
) == (long) SIG_IGN
)
363 #ifdef HAVE_SIGACTION
364 action
.sa_handler
= (SIGRETTYPE (*) (int)) SCM_INUM (handler
);
366 chandler
= (SIGRETTYPE (*) (int)) SCM_INUM (handler
);
368 install_handler (csig
, SCM_BOOL_F
, SCM_BOOL_F
);
371 SCM_OUT_OF_RANGE (2, handler
);
373 else if (SCM_FALSEP (handler
))
375 /* restore the default handler. */
376 #ifdef HAVE_SIGACTION
377 if (orig_handlers
[csig
].sa_handler
== SIG_ERR
)
381 action
= orig_handlers
[csig
];
382 orig_handlers
[csig
].sa_handler
= SIG_ERR
;
383 install_handler (csig
, SCM_BOOL_F
, SCM_BOOL_F
);
386 if (orig_handlers
[csig
] == SIG_ERR
)
390 chandler
= orig_handlers
[csig
];
391 orig_handlers
[csig
] = SIG_ERR
;
392 install_handler (csig
, SCM_BOOL_F
, SCM_BOOL_F
);
398 SCM_VALIDATE_NIM (2, handler
);
399 #ifdef HAVE_SIGACTION
400 action
.sa_handler
= take_signal
;
401 if (orig_handlers
[csig
].sa_handler
== SIG_ERR
)
404 chandler
= take_signal
;
405 if (orig_handlers
[csig
] == SIG_ERR
)
408 install_handler (csig
, thread
, handler
);
411 /* XXX - Silently ignore setting handlers for `program error signals'
412 because they can't currently be handled by Scheme code.
417 /* This list of program error signals is from the GNU Libc
426 #if defined(SIGIOT) && (SIGIOT != SIGABRT)
441 #ifdef HAVE_SIGACTION
444 if (sigaction (csig
, 0, &old_action
) == -1)
449 if (sigaction (csig
, &action
, &old_action
) == -1)
452 orig_handlers
[csig
] = old_action
;
454 if (old_action
.sa_handler
== SIG_DFL
|| old_action
.sa_handler
== SIG_IGN
)
455 old_handler
= scm_long2num ((long) old_action
.sa_handler
);
457 return scm_cons (old_handler
, SCM_MAKINUM (old_action
.sa_flags
));
461 if ((old_chandler
= signal (csig
, SIG_IGN
)) == SIG_ERR
)
463 if (signal (csig
, old_chandler
) == SIG_ERR
)
468 if ((old_chandler
= signal (csig
, chandler
)) == SIG_ERR
)
471 orig_handlers
[csig
] = old_chandler
;
473 if (old_chandler
== SIG_DFL
|| old_chandler
== SIG_IGN
)
474 old_handler
= scm_long2num ((long) old_chandler
);
476 return scm_cons (old_handler
, SCM_MAKINUM (0));
481 SCM_DEFINE (scm_restore_signals
, "restore-signals", 0, 0, 0,
483 "Return all signal handlers to the values they had before any call to\n"
484 "@code{sigaction} was made. The return value is unspecified.")
485 #define FUNC_NAME s_scm_restore_signals
488 for (i
= 0; i
< NSIG
; i
++)
490 #ifdef HAVE_SIGACTION
491 if (orig_handlers
[i
].sa_handler
!= SIG_ERR
)
493 if (sigaction (i
, &orig_handlers
[i
], NULL
) == -1)
495 orig_handlers
[i
].sa_handler
= SIG_ERR
;
496 SCM_VECTOR_SET (*signal_handlers
, i
, SCM_BOOL_F
);
499 if (orig_handlers
[i
] != SIG_ERR
)
501 if (signal (i
, orig_handlers
[i
]) == SIG_ERR
)
503 orig_handlers
[i
] = SIG_ERR
;
504 SCM_VECTOR_SET (*signal_handlers
, i
, SCM_BOOL_F
);
508 return SCM_UNSPECIFIED
;
512 SCM_DEFINE (scm_alarm
, "alarm", 1, 0, 0,
514 "Set a timer to raise a @code{SIGALRM} signal after the specified\n"
515 "number of seconds (an integer). It's advisable to install a signal\n"
517 "@code{SIGALRM} beforehand, since the default action is to terminate\n"
519 "The return value indicates the time remaining for the previous alarm,\n"
520 "if any. The new value replaces the previous alarm. If there was\n"
521 "no previous alarm, the return value is zero.")
522 #define FUNC_NAME s_scm_alarm
525 SCM_VALIDATE_INUM (1, i
);
526 j
= alarm (SCM_INUM (i
));
527 return SCM_MAKINUM (j
);
531 #ifdef HAVE_SETITIMER
532 SCM_DEFINE (scm_setitimer
, "setitimer", 5, 0, 0,
534 SCM interval_seconds
, SCM interval_microseconds
,
535 SCM value_seconds
, SCM value_microseconds
),
536 "Set the timer specified by @var{which_timer} according to the given\n"
537 "@var{interval_seconds}, @var{interval_microseconds},\n"
538 "@var{value_seconds}, and @var{value_microseconds} values.\n"
540 "Return information about the timer's previous setting."
542 "Errors are handled as described in the guile info pages under ``POSIX\n"
543 "Interface Conventions''.\n"
545 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
546 "and @code{ITIMER_PROF}.\n"
548 "The return value will be a list of two cons pairs representing the\n"
549 "current state of the given timer. The first pair is the seconds and\n"
550 "microseconds of the timer @code{it_interval}, and the second pair is\n"
551 "the seconds and microseconds of the timer @code{it_value}.")
552 #define FUNC_NAME s_scm_setitimer
556 struct itimerval new_timer
;
557 struct itimerval old_timer
;
559 c_which_timer
= SCM_NUM2INT(1, which_timer
);
560 new_timer
.it_interval
.tv_sec
= SCM_NUM2LONG(2, interval_seconds
);
561 new_timer
.it_interval
.tv_usec
= SCM_NUM2LONG(3, interval_microseconds
);
562 new_timer
.it_value
.tv_sec
= SCM_NUM2LONG(4, value_seconds
);
563 new_timer
.it_value
.tv_usec
= SCM_NUM2LONG(5, value_microseconds
);
565 SCM_SYSCALL(rv
= setitimer(c_which_timer
, &new_timer
, &old_timer
));
570 return scm_list_2(scm_cons(scm_long2num(old_timer
.it_interval
.tv_sec
),
571 scm_long2num(old_timer
.it_interval
.tv_usec
)),
572 scm_cons(scm_long2num(old_timer
.it_value
.tv_sec
),
573 scm_long2num(old_timer
.it_value
.tv_usec
)));
576 #endif /* HAVE_SETITIMER */
578 #ifdef HAVE_GETITIMER
579 SCM_DEFINE (scm_getitimer
, "getitimer", 1, 0, 0,
581 "Return information about the timer specified by @var{which_timer}"
583 "Errors are handled as described in the guile info pages under ``POSIX\n"
584 "Interface Conventions''.\n"
586 "The timers available are: @code{ITIMER_REAL}, @code{ITIMER_VIRTUAL},\n"
587 "and @code{ITIMER_PROF}.\n"
589 "The return value will be a list of two cons pairs representing the\n"
590 "current state of the given timer. The first pair is the seconds and\n"
591 "microseconds of the timer @code{it_interval}, and the second pair is\n"
592 "the seconds and microseconds of the timer @code{it_value}.")
593 #define FUNC_NAME s_scm_getitimer
597 struct itimerval old_timer
;
599 c_which_timer
= SCM_NUM2INT(1, which_timer
);
601 SCM_SYSCALL(rv
= getitimer(c_which_timer
, &old_timer
));
606 return scm_list_2(scm_cons(scm_long2num(old_timer
.it_interval
.tv_sec
),
607 scm_long2num(old_timer
.it_interval
.tv_usec
)),
608 scm_cons(scm_long2num(old_timer
.it_value
.tv_sec
),
609 scm_long2num(old_timer
.it_value
.tv_usec
)));
612 #endif /* HAVE_GETITIMER */
615 SCM_DEFINE (scm_pause
, "pause", 0, 0, 0,
617 "Pause the current process (thread?) until a signal arrives whose\n"
618 "action is to either terminate the current process or invoke a\n"
619 "handler procedure. The return value is unspecified.")
620 #define FUNC_NAME s_scm_pause
623 return SCM_UNSPECIFIED
;
628 SCM_DEFINE (scm_sleep
, "sleep", 1, 0, 0,
630 "Wait for the given number of seconds (an integer) or until a signal\n"
631 "arrives. The return value is zero if the time elapses or the number\n"
632 "of seconds remaining otherwise.")
633 #define FUNC_NAME s_scm_sleep
636 SCM_VALIDATE_INUM_MIN (1, i
,0);
637 j
= scm_thread_sleep (SCM_INUM(i
));
638 return scm_ulong2num (j
);
642 SCM_DEFINE (scm_usleep
, "usleep", 1, 0, 0,
644 "Sleep for I microseconds. @code{usleep} is not available on\n"
646 #define FUNC_NAME s_scm_usleep
649 SCM_VALIDATE_INUM_MIN (1, i
,0);
650 j
= scm_thread_usleep (SCM_INUM (i
));
651 return scm_ulong2num (j
);
655 SCM_DEFINE (scm_raise
, "raise", 1, 0, 0,
657 "Sends a specified signal @var{sig} to the current process, where\n"
658 "@var{sig} is as described for the kill procedure.")
659 #define FUNC_NAME s_scm_raise
661 SCM_VALIDATE_INUM (1, sig
);
663 if (kill (getpid (), (int) SCM_INUM (sig
)) != 0)
666 return SCM_UNSPECIFIED
;
678 SCM_VARIABLE_LOC (scm_c_define ("signal-handlers",
679 scm_c_make_vector (NSIG
, SCM_BOOL_F
)));
680 signal_handler_cells
=
681 scm_permanent_object (scm_c_make_vector (NSIG
, SCM_BOOL_F
));
682 signal_cell_handlers
=
683 scm_permanent_object (scm_c_make_vector (NSIG
, SCM_BOOL_F
));
684 signal_handler_threads
=
685 scm_permanent_object (scm_c_make_vector (NSIG
, SCM_BOOL_F
));
687 for (i
= 0; i
< NSIG
; i
++)
689 #ifdef HAVE_SIGACTION
690 orig_handlers
[i
].sa_handler
= SIG_ERR
;
693 orig_handlers
[i
] = SIG_ERR
;
696 #ifdef HAVE_RESTARTABLE_SYSCALLS
697 /* If HAVE_RESTARTABLE_SYSCALLS is defined, it's important that
698 signals really are restartable. don't rely on the same
699 run-time that configure got: reset the default for every signal.
701 #ifdef HAVE_SIGINTERRUPT
703 #elif defined(SA_RESTART)
705 struct sigaction action
;
707 sigaction (i
, NULL
, &action
);
708 if (!(action
.sa_flags
& SA_RESTART
))
710 action
.sa_flags
|= SA_RESTART
;
711 sigaction (i
, &action
, NULL
);
715 /* if neither siginterrupt nor SA_RESTART are available we may
716 as well assume that signals are always restartable. */
720 scm_c_define ("NSIG", scm_long2num (NSIG
));
721 scm_c_define ("SIG_IGN", scm_long2num ((long) SIG_IGN
));
722 scm_c_define ("SIG_DFL", scm_long2num ((long) SIG_DFL
));
724 scm_c_define ("SA_NOCLDSTOP", scm_long2num (SA_NOCLDSTOP
));
727 scm_c_define ("SA_RESTART", scm_long2num (SA_RESTART
));
730 #if defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER)
731 /* Stuff needed by setitimer and getitimer. */
732 scm_c_define ("ITIMER_REAL", SCM_MAKINUM (ITIMER_REAL
));
733 scm_c_define ("ITIMER_VIRTUAL", SCM_MAKINUM (ITIMER_VIRTUAL
));
734 scm_c_define ("ITIMER_PROF", SCM_MAKINUM (ITIMER_PROF
));
735 #endif /* defined(HAVE_SETITIMER) || defined(HAVE_GETITIMER) */
737 #include "libguile/scmsigs.x"