scmsigs.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
  2. *
  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)
  6. * any later version.
  7. *
  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.
  12. *
  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
  17. *
  18. * As a special exception, the Free Software Foundation gives permission
  19. * for additional uses of the text contained in its release of GUILE.
  20. *
  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.
  26. *
  27. * This exception does not however invalidate any other reasons why
  28. * the executable file might be covered by the GNU General Public License.
  29. *
  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.
  37. *
  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. */
  41. #include <stdio.h>
  42. #include <signal.h>
  43. #include "libguile/_scm.h"
  44. #include "libguile/async.h"
  45. #include "libguile/eval.h"
  46. #include "libguile/vectors.h"
  47. #include "libguile/validate.h"
  48. #include "libguile/scmsigs.h"
  49. #ifdef HAVE_UNISTD_H
  50. #include <unistd.h>
  51. #endif
  52. /* The thread system has its own sleep and usleep functions. */
  53. #ifndef USE_THREADS
  54. #if defined(MISSING_SLEEP_DECL)
  55. int sleep ();
  56. #endif
  57. #if defined(HAVE_USLEEP) && defined(MISSING_USLEEP_DECL)
  58. int usleep ();
  59. #endif
  60. #endif
  61. /* SIGRETTYPE is the type that signal handlers return. See <signal.h> */
  62. #ifdef RETSIGTYPE
  63. # define SIGRETTYPE RETSIGTYPE
  64. #else
  65. # ifdef STDC_HEADERS
  66. # define SIGRETTYPE void
  67. # else
  68. # define SIGRETTYPE int
  69. # endif
  70. #endif
  71. /* take_signal is installed as the C signal handler whenever a Scheme
  72. handler is set. when a signal arrives, take_signal marks the corresponding
  73. element of got_signal and marks signal_async. the thunk in signal_async
  74. (sys_deliver_signals) will be run at the next opportunity, outside a
  75. critical section. sys_deliver_signals runs each Scheme handler for
  76. which got_signal is set. */
  77. static SCM signal_async;
  78. static char got_signal[NSIG];
  79. /* a Scheme vector of handler procedures. */
  80. static SCM *signal_handlers;
  81. /* saves the original C handlers, when a new handler is installed.
  82. set to SIG_ERR if the original handler is installed. */
  83. #ifdef HAVE_SIGACTION
  84. static struct sigaction orig_handlers[NSIG];
  85. #else
  86. static SIGRETTYPE (*orig_handlers[NSIG])(int);
  87. #endif
  88. static SIGRETTYPE
  89. take_signal (int signum)
  90. {
  91. int saved_errno = errno;
  92. SCM ignored;
  93. if (!scm_ints_disabled)
  94. {
  95. /* For reasons of speed, the SCM_NEWCELL macro doesn't defer
  96. interrupts. Instead, it first sets its argument to point to
  97. the first cell in the list, and then advances the freelist
  98. pointer to the next cell. Now, if this procedure is
  99. interrupted, the only anomalous state possible is to have
  100. both SCM_NEWCELL's argument and scm_freelist pointing to the
  101. same cell. To deal with this case, we always throw away the
  102. first cell in scm_freelist here.
  103. At least, that's the theory. I'm not convinced that that's
  104. the only anomalous path we need to worry about. */
  105. SCM_NEWCELL (ignored);
  106. }
  107. got_signal[signum] = 1;
  108. #if HAVE_SIGACTION
  109. /* unblock the signal before the scheme handler gets to run, since
  110. it may use longjmp to escape (i.e., throw an exception). */
  111. {
  112. sigset_t set;
  113. sigemptyset (&set);
  114. sigaddset (&set, signum);
  115. sigprocmask (SIG_UNBLOCK, &set, NULL);
  116. }
  117. #endif
  118. scm_system_async_mark (signal_async);
  119. errno = saved_errno;
  120. }
  121. static SCM
  122. sys_deliver_signals (void)
  123. {
  124. int i;
  125. for (i = 0; i < NSIG; i++)
  126. {
  127. if (got_signal[i])
  128. {
  129. /* The flag is reset before calling the handler in case the
  130. handler doesn't return. If the handler doesn't return
  131. but leaves other signals flagged, they their handlers
  132. will be applied some time later when the async is checked
  133. again. It would probably be better to reset the flags
  134. after doing a longjmp. */
  135. got_signal[i] = 0;
  136. #ifndef HAVE_SIGACTION
  137. signal (i, take_signal);
  138. #endif
  139. scm_apply (SCM_VELTS (*signal_handlers)[i],
  140. scm_listify (SCM_MAKINUM (i), SCM_UNDEFINED),
  141. SCM_EOL);
  142. }
  143. }
  144. return SCM_UNSPECIFIED;
  145. }
  146. /* user interface for installation of signal handlers. */
  147. SCM_DEFINE (scm_sigaction, "sigaction", 1, 2, 0,
  148. (SCM signum, SCM handler, SCM flags),
  149. "Install or report the signal handler for a specified signal.\n\n"
  150. "@var{signum} is the signal number, which can be specified using the value\n"
  151. "of variables such as @code{SIGINT}.\n\n"
  152. "If @var{action} is omitted, @code{sigaction} returns a pair: the\n"
  153. "CAR is the current\n"
  154. "signal hander, which will be either an integer with the value @code{SIG_DFL}\n"
  155. "(default action) or @code{SIG_IGN} (ignore), or the Scheme procedure which\n"
  156. "handles the signal, or @code{#f} if a non-Scheme procedure handles the\n"
  157. "signal. The CDR contains the current @code{sigaction} flags for the handler.\n\n"
  158. "If @var{action} is provided, it is installed as the new handler for\n"
  159. "@var{signum}. @var{action} can be a Scheme procedure taking one\n"
  160. "argument, or the value of @code{SIG_DFL} (default action) or\n"
  161. "@code{SIG_IGN} (ignore), or @code{#f} to restore whatever signal handler\n"
  162. "was installed before @code{sigaction} was first used. Flags can\n"
  163. "optionally be specified for the new handler (@code{SA_RESTART} will\n"
  164. "always be added if it's available and the system is using restartable\n"
  165. "system calls.) The return value is a pair with information about the\n"
  166. "old handler as described above.\n\n"
  167. "This interface does not provide access to the \"signal blocking\"\n"
  168. "facility. Maybe this is not needed, since the thread support may\n"
  169. "provide solutions to the problem of consistent access to data\n"
  170. "structures.")
  171. #define FUNC_NAME s_scm_sigaction
  172. {
  173. int csig;
  174. #ifdef HAVE_SIGACTION
  175. struct sigaction action;
  176. struct sigaction old_action;
  177. #else
  178. SIGRETTYPE (* chandler) (int);
  179. SIGRETTYPE (* old_chandler) (int);
  180. #endif
  181. int query_only = 0;
  182. int save_handler = 0;
  183. SCM *scheme_handlers = SCM_VELTS (*signal_handlers);
  184. SCM old_handler;
  185. SCM_VALIDATE_INUM_COPY (1,signum,csig);
  186. #if defined(HAVE_SIGACTION)
  187. #if defined(SA_RESTART) && defined(HAVE_RESTARTABLE_SYSCALLS)
  188. /* don't allow SA_RESTART to be omitted if HAVE_RESTARTABLE_SYSCALLS
  189. is defined, since libguile would be likely to produce spurious
  190. EINTR errors. */
  191. action.sa_flags = SA_RESTART;
  192. #else
  193. action.sa_flags = 0;
  194. #endif
  195. if (!SCM_UNBNDP (flags))
  196. {
  197. SCM_VALIDATE_INUM (3,flags);
  198. action.sa_flags |= SCM_INUM (flags);
  199. }
  200. sigemptyset (&action.sa_mask);
  201. #endif
  202. SCM_DEFER_INTS;
  203. old_handler = scheme_handlers[csig];
  204. if (SCM_UNBNDP (handler))
  205. query_only = 1;
  206. else if (SCM_EQ_P (scm_integer_p (handler), SCM_BOOL_T))
  207. {
  208. if (SCM_NUM2LONG (2,handler) == (long) SIG_DFL
  209. || SCM_NUM2LONG (2,handler) == (long) SIG_IGN)
  210. {
  211. #ifdef HAVE_SIGACTION
  212. action.sa_handler = (SIGRETTYPE (*) (int)) SCM_INUM (handler);
  213. #else
  214. chandler = (SIGRETTYPE (*) (int)) SCM_INUM (handler);
  215. #endif
  216. scheme_handlers[csig] = SCM_BOOL_F;
  217. }
  218. else
  219. SCM_OUT_OF_RANGE (2, handler);
  220. }
  221. else if (SCM_FALSEP (handler))
  222. {
  223. /* restore the default handler. */
  224. #ifdef HAVE_SIGACTION
  225. if (orig_handlers[csig].sa_handler == SIG_ERR)
  226. query_only = 1;
  227. else
  228. {
  229. action = orig_handlers[csig];
  230. orig_handlers[csig].sa_handler = SIG_ERR;
  231. scheme_handlers[csig] = SCM_BOOL_F;
  232. }
  233. #else
  234. if (orig_handlers[csig] == SIG_ERR)
  235. query_only = 1;
  236. else
  237. {
  238. chandler = orig_handlers[csig];
  239. orig_handlers[csig] = SIG_ERR;
  240. scheme_handlers[csig] = SCM_BOOL_F;
  241. }
  242. #endif
  243. }
  244. else
  245. {
  246. SCM_VALIDATE_NIM (2,handler);
  247. #ifdef HAVE_SIGACTION
  248. action.sa_handler = take_signal;
  249. if (orig_handlers[csig].sa_handler == SIG_ERR)
  250. save_handler = 1;
  251. #else
  252. chandler = take_signal;
  253. if (orig_handlers[csig] == SIG_ERR)
  254. save_handler = 1;
  255. #endif
  256. scheme_handlers[csig] = handler;
  257. }
  258. /* XXX - Silently ignore setting handlers for `program error signals'
  259. because they can't currently be handled by Scheme code.
  260. */
  261. switch (csig)
  262. {
  263. /* This list of program error signals is from the GNU Libc
  264. Reference Manual */
  265. case SIGFPE:
  266. case SIGILL:
  267. case SIGSEGV:
  268. case SIGBUS:
  269. case SIGABRT:
  270. #if defined(SIGIOT) && (SIGIOT != SIGABRT)
  271. case SIGIOT:
  272. #endif
  273. case SIGTRAP:
  274. #ifdef SIGEMT
  275. case SIGEMT:
  276. #endif
  277. #ifdef SIGSYS
  278. case SIGSYS:
  279. #endif
  280. query_only = 1;
  281. }
  282. #ifdef HAVE_SIGACTION
  283. if (query_only)
  284. {
  285. if (sigaction (csig, 0, &old_action) == -1)
  286. SCM_SYSERROR;
  287. }
  288. else
  289. {
  290. if (sigaction (csig, &action , &old_action) == -1)
  291. SCM_SYSERROR;
  292. if (save_handler)
  293. orig_handlers[csig] = old_action;
  294. }
  295. if (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN)
  296. old_handler = scm_long2num ((long) old_action.sa_handler);
  297. SCM_ALLOW_INTS;
  298. return scm_cons (old_handler, SCM_MAKINUM (old_action.sa_flags));
  299. #else
  300. if (query_only)
  301. {
  302. if ((old_chandler = signal (csig, SIG_IGN)) == SIG_ERR)
  303. SCM_SYSERROR;
  304. if (signal (csig, old_chandler) == SIG_ERR)
  305. SCM_SYSERROR;
  306. }
  307. else
  308. {
  309. if ((old_chandler = signal (csig, chandler)) == SIG_ERR)
  310. SCM_SYSERROR;
  311. if (save_handler)
  312. orig_handlers[csig] = old_chandler;
  313. }
  314. if (old_chandler == SIG_DFL || old_chandler == SIG_IGN)
  315. old_handler = scm_long2num ((long) old_chandler);
  316. SCM_ALLOW_INTS;
  317. return scm_cons (old_handler, SCM_MAKINUM (0));
  318. #endif
  319. }
  320. #undef FUNC_NAME
  321. SCM_DEFINE (scm_restore_signals, "restore-signals", 0, 0, 0,
  322. (void),
  323. "Return all signal handlers to the values they had before any call to\n"
  324. "@code{sigaction} was made. The return value is unspecified.")
  325. #define FUNC_NAME s_scm_restore_signals
  326. {
  327. int i;
  328. SCM *scheme_handlers = SCM_VELTS (*signal_handlers);
  329. for (i = 0; i < NSIG; i++)
  330. {
  331. #ifdef HAVE_SIGACTION
  332. if (orig_handlers[i].sa_handler != SIG_ERR)
  333. {
  334. if (sigaction (i, &orig_handlers[i], NULL) == -1)
  335. SCM_SYSERROR;
  336. orig_handlers[i].sa_handler = SIG_ERR;
  337. scheme_handlers[i] = SCM_BOOL_F;
  338. }
  339. #else
  340. if (orig_handlers[i] != SIG_ERR)
  341. {
  342. if (signal (i, orig_handlers[i]) == SIG_ERR)
  343. SCM_SYSERROR;
  344. orig_handlers[i] = SIG_ERR;
  345. scheme_handlers[i] = SCM_BOOL_F;
  346. }
  347. #endif
  348. }
  349. return SCM_UNSPECIFIED;
  350. }
  351. #undef FUNC_NAME
  352. SCM_DEFINE (scm_alarm, "alarm", 1, 0, 0,
  353. (SCM i),
  354. "Set a timer to raise a @code{SIGALRM} signal after the specified\n"
  355. "number of seconds (an integer). It's advisable to install a signal\n"
  356. "handler for\n"
  357. "@code{SIGALRM} beforehand, since the default action is to terminate\n"
  358. "the process.\n\n"
  359. "The return value indicates the time remaining for the previous alarm,\n"
  360. "if any. The new value replaces the previous alarm. If there was\n"
  361. "no previous alarm, the return value is zero.")
  362. #define FUNC_NAME s_scm_alarm
  363. {
  364. unsigned int j;
  365. SCM_VALIDATE_INUM (1,i);
  366. j = alarm (SCM_INUM (i));
  367. return SCM_MAKINUM (j);
  368. }
  369. #undef FUNC_NAME
  370. #ifdef HAVE_PAUSE
  371. SCM_DEFINE (scm_pause, "pause", 0, 0, 0,
  372. (),
  373. "Pause the current process (thread?) until a signal arrives whose\n"
  374. "action is to either terminate the current process or invoke a\n"
  375. "handler procedure. The return value is unspecified.")
  376. #define FUNC_NAME s_scm_pause
  377. {
  378. pause ();
  379. return SCM_UNSPECIFIED;
  380. }
  381. #undef FUNC_NAME
  382. #endif
  383. SCM_DEFINE (scm_sleep, "sleep", 1, 0, 0,
  384. (SCM i),
  385. "Wait for the given number of seconds (an integer) or until a signal\n"
  386. "arrives. The return value is zero if the time elapses or the number\n"
  387. "of seconds remaining otherwise.")
  388. #define FUNC_NAME s_scm_sleep
  389. {
  390. unsigned long j;
  391. SCM_VALIDATE_INUM_MIN (1,i,0);
  392. #ifdef USE_THREADS
  393. j = scm_thread_sleep (SCM_INUM(i));
  394. #else
  395. j = sleep (SCM_INUM(i));
  396. #endif
  397. return scm_ulong2num (j);
  398. }
  399. #undef FUNC_NAME
  400. #if defined(USE_THREADS) || defined(HAVE_USLEEP)
  401. SCM_DEFINE (scm_usleep, "usleep", 1, 0, 0,
  402. (SCM i),
  403. "Sleep for I microseconds.\n"
  404. "`usleep' is not available on all platforms.")
  405. #define FUNC_NAME s_scm_usleep
  406. {
  407. SCM_VALIDATE_INUM_MIN (1,i,0);
  408. #ifdef USE_THREADS
  409. /* If we have threads, we use the thread system's sleep function. */
  410. {
  411. unsigned long j = scm_thread_usleep (SCM_INUM (i));
  412. return scm_ulong2num (j);
  413. }
  414. #else
  415. #ifdef USLEEP_RETURNS_VOID
  416. usleep (SCM_INUM (i));
  417. return SCM_INUM0;
  418. #else
  419. {
  420. int j = usleep (SCM_INUM (i));
  421. return SCM_MAKINUM (j);
  422. }
  423. #endif
  424. #endif
  425. }
  426. #undef FUNC_NAME
  427. #endif /* GUILE_ISELECT || HAVE_USLEEP */
  428. SCM_DEFINE (scm_raise, "raise", 1, 0, 0,
  429. (SCM sig),
  430. "\n"
  431. "Sends a specified signal @var{sig} to the current process, where\n"
  432. "@var{sig} is as described for the kill procedure.")
  433. #define FUNC_NAME s_scm_raise
  434. {
  435. SCM_VALIDATE_INUM (1,sig);
  436. SCM_DEFER_INTS;
  437. if (kill (getpid (), (int) SCM_INUM (sig)) != 0)
  438. SCM_SYSERROR;
  439. SCM_ALLOW_INTS;
  440. return SCM_UNSPECIFIED;
  441. }
  442. #undef FUNC_NAME
  443. void
  444. scm_init_scmsigs ()
  445. {
  446. SCM thunk;
  447. int i;
  448. signal_handlers =
  449. SCM_CDRLOC (scm_sysintern ("signal-handlers",
  450. scm_make_vector (SCM_MAKINUM (NSIG),
  451. SCM_BOOL_F)));
  452. thunk = scm_make_gsubr ("%deliver-signals", 0, 0, 0,
  453. sys_deliver_signals);
  454. signal_async = scm_system_async (thunk);
  455. for (i = 0; i < NSIG; i++)
  456. {
  457. got_signal[i] = 0;
  458. #ifdef HAVE_SIGACTION
  459. orig_handlers[i].sa_handler = SIG_ERR;
  460. #else
  461. orig_handlers[i] = SIG_ERR;
  462. #endif
  463. #ifdef HAVE_RESTARTABLE_SYSCALLS
  464. /* If HAVE_RESTARTABLE_SYSCALLS is defined, it's important that
  465. signals really are restartable. don't rely on the same
  466. run-time that configure got: reset the default for every signal.
  467. */
  468. #ifdef HAVE_SIGINTERRUPT
  469. siginterrupt (i, 0);
  470. #elif defined(SA_RESTART)
  471. {
  472. struct sigaction action;
  473. sigaction (i, NULL, &action);
  474. if (!(action.sa_flags & SA_RESTART))
  475. {
  476. action.sa_flags |= SA_RESTART;
  477. sigaction (i, &action, NULL);
  478. }
  479. }
  480. #endif
  481. /* if neither siginterrupt nor SA_RESTART are available we may
  482. as well assume that signals are always restartable. */
  483. #endif
  484. }
  485. scm_sysintern ("NSIG", scm_long2num (NSIG));
  486. scm_sysintern ("SIG_IGN", scm_long2num ((long) SIG_IGN));
  487. scm_sysintern ("SIG_DFL", scm_long2num ((long) SIG_DFL));
  488. #ifdef SA_NOCLDSTOP
  489. scm_sysintern ("SA_NOCLDSTOP", scm_long2num (SA_NOCLDSTOP));
  490. #endif
  491. #ifdef SA_RESTART
  492. scm_sysintern ("SA_RESTART", scm_long2num (SA_RESTART));
  493. #endif
  494. #include "libguile/scmsigs.x"
  495. }
  496. /*
  497. Local Variables:
  498. c-file-style: "gnu"
  499. End:
  500. */