Mercurial > hg > xemacs-beta
comparison src/signal.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | abe6d1db359e |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* Handling asynchronous signals. | |
2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. | |
3 Copyright (C) 1995, 1996 Ben Wing. | |
4 | |
5 This file is part of XEmacs. | |
6 | |
7 XEmacs is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Synched up with: Not synched with FSF. Split out of keyboard.c. */ | |
23 | |
24 #include <config.h> | |
25 #include "lisp.h" | |
26 | |
27 #include "console.h" | |
28 #include "events.h" /* for signal_fake_event() */ | |
29 #include "frame.h" | |
30 #include "sysdep.h" | |
31 #include "syssignal.h" | |
32 #include "systime.h" | |
33 | |
34 #ifdef HAVE_UNISTD_H | |
35 #include <unistd.h> | |
36 #endif | |
37 #include <errno.h> | |
38 | |
39 /* Set to 1 when a quit-check signal (either a SIGIO interrupt or | |
40 the asynch. timeout for poll-for-quit) occurs. The QUITP | |
41 macro may look at this. */ | |
42 volatile int quit_check_signal_happened; | |
43 | |
44 /* Count of the number of times a quit-check signal has occurred. | |
45 Some stuff in event-Xt.c looks at this. */ | |
46 volatile int quit_check_signal_tick_count; | |
47 | |
48 /* Set to 1 when a SIGINT (or SIGQUIT) interrupt is processed. | |
49 maybe_read_quit_event() looks at this. */ | |
50 volatile int sigint_happened; | |
51 | |
52 /* Set to 1 when an asynch. timeout signal occurs. */ | |
53 static volatile int alarm_happened; | |
54 | |
55 /* This is used to synchronize setting the waiting_for_user_input_p | |
56 flag. */ | |
57 static volatile int alarm_happened_while_emacs_was_blocking; | |
58 | |
59 /* See check_quit() for when this is set. */ | |
60 int dont_check_for_quit; | |
61 | |
62 #if !defined (SIGIO) && !defined (DONT_POLL_FOR_QUIT) | |
63 int poll_for_quit_id; | |
64 #endif | |
65 | |
66 #if defined(HAVE_UNIX_PROCESSES) && !defined(SIGCHLD) | |
67 int poll_for_sigchld_id; | |
68 #endif | |
69 | |
70 /* This variable is used to communicate to a lisp | |
71 process-filter/sentinel/asynchronous callback (via the function | |
72 Fwaiting_for_user_input_p below) whether XEmacs was waiting for | |
73 user-input when that process-filter was called. */ | |
74 static int waiting_for_user_input_p; | |
75 | |
76 static int interrupts_slowed_down; | |
77 | |
78 #define SLOWED_DOWN_INTERRUPTS_SECS 15 | |
79 #define NORMAL_QUIT_CHECK_TIMEOUT_MSECS 250 | |
80 #define NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS 250 | |
81 | |
82 /* Used so that signals can break out of system calls that aren't | |
83 naturally interruptible. */ | |
84 | |
85 JMP_BUF break_system_call_jump; | |
86 volatile int can_break_system_calls; | |
87 | |
88 | |
89 /**********************************************************************/ | |
90 /* Asynchronous timeout functions */ | |
91 /**********************************************************************/ | |
92 | |
93 /* The pending timers are stored in an ordered list, where the first timer | |
94 on the list is the first one to fire. Times recorded here are | |
95 absolute. */ | |
96 static struct low_level_timeout *async_timer_queue; | |
97 | |
98 /* Nonzero means async timers are temporarily suppressed. */ | |
99 static int async_timer_suppress_count; | |
100 | |
101 static void | |
102 set_one_shot_timer (EMACS_TIME interval) | |
103 { | |
104 #ifdef HAVE_SETITIMER | |
105 struct itimerval it; | |
106 it.it_value = interval; | |
107 EMACS_SET_SECS_USECS (it.it_interval, 0, 0); | |
108 setitimer (ITIMER_REAL, &it, 0); | |
109 #else | |
110 int secs; | |
111 EMACS_TIME_TO_INT (interval, secs); | |
112 alarm (secs); | |
113 #endif | |
114 } | |
115 | |
116 static void | |
117 reset_interval_timer (void) | |
118 { | |
119 EMACS_TIME interval; | |
120 | |
121 /* Get the interval to set. If an interval is available, | |
122 make sure it's not zero (this is a valid return, but it will | |
123 cause the timer to get disabled, so convert it to a very short | |
124 time). */ | |
125 if (get_low_level_timeout_interval (async_timer_queue, &interval)) | |
126 { | |
127 if (EMACS_SECS (interval) == 0 && EMACS_USECS (interval) == 0) | |
128 EMACS_SET_USECS (interval, 1); | |
129 } | |
130 else | |
131 /* A time of 0 means "disable". */ | |
132 EMACS_SET_SECS_USECS (interval, 0, 0); | |
133 | |
134 set_one_shot_timer (interval); | |
135 } | |
136 | |
137 int | |
138 event_stream_add_async_timeout (EMACS_TIME thyme) | |
139 { | |
140 int id = add_low_level_timeout (&async_timer_queue, thyme); | |
141 | |
142 /* If this timeout is at the head of the queue, then we need to | |
143 set the timer right now for this timeout. Otherwise, things | |
144 are fine as-is; after the timers ahead of us are signalled, | |
145 the timer will be set for us. */ | |
146 | |
147 if (async_timer_queue->id == id) | |
148 reset_interval_timer (); | |
149 | |
150 return id; | |
151 } | |
152 | |
153 void | |
154 event_stream_remove_async_timeout (int id) | |
155 { | |
156 int first = (async_timer_queue && async_timer_queue->id == id); | |
157 remove_low_level_timeout (&async_timer_queue, id); | |
158 | |
159 /* If we removed the timeout from the head of the queue, then | |
160 we need to reset the interval timer right now. */ | |
161 if (first) | |
162 reset_interval_timer (); | |
163 } | |
164 | |
165 /* Handle an alarm once each second and read pending input | |
166 so as to handle a C-g if it comes in. */ | |
167 | |
168 static SIGTYPE | |
169 alarm_signal (int signo) | |
170 { | |
171 if (interrupts_slowed_down) | |
172 { | |
173 something_happened = 1; /* tell QUIT to wake up */ | |
174 /* we are in "slowed-down interrupts" mode; the only alarm | |
175 happening here is the slowed-down quit-check alarm, so | |
176 we set this flag. | |
177 | |
178 Do NOT set alarm_happened, because we don't want anyone | |
179 looking at the timeout queue. We didn't set it and | |
180 it needs to stay the way it is. */ | |
181 quit_check_signal_happened = 1; | |
182 | |
183 #ifdef WINDOWSNT | |
184 can_break_system_calls = 0; | |
185 #else | |
186 /* can_break_system_calls is set when we want to break out of | |
187 non-interruptible system calls. */ | |
188 if (can_break_system_calls) | |
189 { | |
190 /* reset the flag for safety and such. Do this *before* | |
191 unblocking or reestablishing the signal to avoid potential | |
192 race conditions. */ | |
193 can_break_system_calls = 0; | |
194 EMACS_UNBLOCK_SIGNAL (signo); | |
195 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal); | |
196 LONGJMP (break_system_call_jump, 0); | |
197 } | |
198 #endif | |
199 | |
200 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal); | |
201 SIGRETURN; | |
202 } | |
203 | |
204 something_happened = 1; /* tell QUIT to wake up */ | |
205 alarm_happened = 1; | |
206 if (emacs_is_blocking) | |
207 alarm_happened_while_emacs_was_blocking = 1; | |
208 /* #### This is for QUITP. When it is run, it may not be the | |
209 place to do arbitrary stuff like run asynch. handlers, but | |
210 it needs to know whether the poll-for-quit asynch. timeout | |
211 went off. Rather than put the code in to compute this | |
212 specially, we just set this flag. Should fix this. */ | |
213 quit_check_signal_happened = 1; | |
214 | |
215 #ifdef HAVE_UNIXOID_EVENT_LOOP | |
216 signal_fake_event (); | |
217 #endif | |
218 | |
219 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal); | |
220 SIGRETURN; | |
221 } | |
222 | |
223 static void | |
224 init_async_timeouts (void) | |
225 { | |
226 signal (SIGALRM, alarm_signal); | |
227 async_timer_suppress_count = 0; | |
228 } | |
229 | |
230 /* Turn off async timeouts. */ | |
231 | |
232 static void | |
233 stop_async_timeouts (void) | |
234 { | |
235 if (async_timer_suppress_count == 0) | |
236 { | |
237 /* If timer was on, turn it off. */ | |
238 EMACS_TIME thyme; | |
239 EMACS_SET_SECS_USECS (thyme, 0, 0); | |
240 set_one_shot_timer (thyme); | |
241 } | |
242 async_timer_suppress_count++; | |
243 } | |
244 | |
245 /* Turn on async timeouts again. */ | |
246 | |
247 static void | |
248 start_async_timeouts (void) | |
249 { | |
250 assert (async_timer_suppress_count > 0); | |
251 async_timer_suppress_count--; | |
252 if (async_timer_suppress_count == 0) | |
253 { | |
254 /* Some callers turn off async timeouts and then use the alarm | |
255 for their own purposes; so reinitialize everything. */ | |
256 signal (SIGALRM, alarm_signal); | |
257 reset_interval_timer (); | |
258 } | |
259 } | |
260 | |
261 /* Some functions don't like being interrupted with SIGALRM or SIGIO. | |
262 Previously we were calling stop_interrupts() / start_interrupts(), | |
263 but then if the program hangs in one of those functions, e.g. | |
264 waiting for a connect(), we're really screwed. So instead we | |
265 just "slow them down". We do this by disabling all interrupts | |
266 and then installing a timer of length fairly large, like 5 or | |
267 10 secs. That way, any "legitimate" connections (which should | |
268 take a fairly short amount of time) go through OK, but we can | |
269 interrupt bogus ones. */ | |
270 | |
271 void | |
272 slow_down_interrupts (void) | |
273 { | |
274 EMACS_TIME thyme; | |
275 | |
276 /* We have to set the flag *before* setting the slowed-down timer, | |
277 to avoid a race condition -- if the signal occurs between the | |
278 call to set_one_shot_timer() and the setting of this flag, | |
279 alarm_happened will get set, which will be a Bad Thing if | |
280 there were no timeouts on the queue. */ | |
281 interrupts_slowed_down++; | |
282 if (interrupts_slowed_down == 1) | |
283 { | |
284 stop_interrupts (); | |
285 EMACS_SET_SECS_USECS (thyme, SLOWED_DOWN_INTERRUPTS_SECS, 0); | |
286 set_one_shot_timer (thyme); | |
287 } | |
288 } | |
289 | |
290 void | |
291 speed_up_interrupts (void) | |
292 { | |
293 if (interrupts_slowed_down > 0) | |
294 { | |
295 start_interrupts (); | |
296 /* Change this flag AFTER fiddling with interrupts, for the same | |
297 race-condition reasons as above. */ | |
298 interrupts_slowed_down--; | |
299 } | |
300 } | |
301 | |
302 static void | |
303 handle_alarm_going_off (void) | |
304 { | |
305 int interval_id; | |
306 | |
307 /* If asynch. timeouts are blocked, then don't do anything now, | |
308 but make this function get called again next QUIT. | |
309 | |
310 #### This is a bit inefficient because there will be function call | |
311 overhead each time QUIT occurs. */ | |
312 | |
313 if (!NILP (Vinhibit_quit)) | |
314 { | |
315 something_happened = 1; | |
316 alarm_happened = 1; | |
317 return; | |
318 } | |
319 | |
320 interval_id = pop_low_level_timeout (&async_timer_queue, 0); | |
321 | |
322 reset_interval_timer (); | |
323 if (alarm_happened_while_emacs_was_blocking) | |
324 { | |
325 alarm_happened_while_emacs_was_blocking = 0; | |
326 waiting_for_user_input_p = 1; | |
327 } | |
328 event_stream_deal_with_async_timeout (interval_id); | |
329 waiting_for_user_input_p = 0; | |
330 } | |
331 | |
332 #ifdef HAVE_SETITIMER | |
333 unsigned int | |
334 alarm (unsigned int howlong) | |
335 { | |
336 struct itimerval old_it, new_it; | |
337 | |
338 /* If alarm() gets called when polling isn't disabled, it can mess | |
339 up the periodic timer. */ | |
340 assert (async_timer_suppress_count > 0); | |
341 | |
342 new_it.it_value.tv_sec = howlong; | |
343 new_it.it_value.tv_usec = 0; | |
344 new_it.it_interval.tv_sec = 0; | |
345 new_it.it_interval.tv_usec = 0; | |
346 setitimer (ITIMER_REAL, &new_it, &old_it); | |
347 | |
348 /* Never return zero if there was a timer outstanding. */ | |
349 return old_it.it_value.tv_sec + (old_it.it_value.tv_usec > 0 ? 1 : 0); | |
350 } | |
351 #endif | |
352 | |
353 DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, 0, 0, 0, /* | |
354 Return non-nil if XEmacs is waiting for input from the user. | |
355 This is intended for use by asynchronous timeout callbacks and by | |
356 asynchronous process output filters and sentinels (not yet implemented | |
357 in XEmacs). It will always be nil if XEmacs is not inside of | |
358 an asynchronous timeout or process callback. | |
359 */ | |
360 ()) | |
361 { | |
362 return waiting_for_user_input_p ? Qt : Qnil; | |
363 } | |
364 | |
365 | |
366 /**********************************************************************/ | |
367 /* Control-G checking */ | |
368 /**********************************************************************/ | |
369 | |
370 /* Set this for debugging, to have a way to get out */ | |
371 int stop_character; /* #### not currently implemented */ | |
372 | |
373 /* This routine is called in response to a SIGINT or SIGQUIT. | |
374 On TTY's, one of these two signals will get generated in response | |
375 to C-g. (When running under X, C-g is handled using the SIGIO | |
376 handler, which sets a flag telling the QUIT macro to scan the | |
377 unread events for a ^G.) | |
378 | |
379 Otherwise it sets the Lisp variable quit-flag not-nil. | |
380 This causes eval to throw, when it gets a chance. | |
381 If quit-flag is already non-nil, it stops the job right away. */ | |
382 | |
383 static SIGTYPE | |
384 interrupt_signal (int sig) | |
385 { | |
386 /* This function can call lisp */ | |
387 /* #### we should NOT be calling lisp from a signal handler, boys | |
388 and girls */ | |
389 /* Must preserve main program's value of errno. */ | |
390 int old_errno = errno; | |
391 | |
392 EMACS_REESTABLISH_SIGNAL (sig, interrupt_signal); | |
393 | |
394 /* with the macroized error-checking stuff, the garbage below | |
395 may mess things up because XCONSOLE() and such can use and | |
396 change global vars. */ | |
397 #if ! (defined (ERROR_CHECK_TYPECHECK) && defined (MACROIZE_ERROR_CHECKING)) | |
398 if (sigint_happened && CONSOLEP (Vcontrolling_terminal) && | |
399 CONSOLE_LIVE_P (XCONSOLE (Vcontrolling_terminal)) && | |
400 !emacs_is_blocking) | |
401 { | |
402 char c; | |
403 fflush (stdout); | |
404 reset_initial_console (); | |
405 EMACS_UNBLOCK_SIGNAL (sig); | |
406 #ifdef SIGTSTP /* Support possible in later USG versions */ | |
407 /* | |
408 * On systems which can suspend the current process and return to the original | |
409 * shell, this command causes the user to end up back at the shell. | |
410 * The "Auto-save" and "Abort" questions are not asked until | |
411 * the user elects to return to emacs, at which point he can save the current | |
412 * job and either dump core or continue. | |
413 */ | |
414 sys_suspend (); | |
415 #else | |
416 /* Perhaps should really fork an inferior shell? | |
417 But that would not provide any way to get back | |
418 to the original shell, ever. */ | |
419 stdout_out ("No support for stopping a process on this operating system;\n"); | |
420 stdout_out ("you can continue or abort.\n"); | |
421 #endif /* not SIGTSTP */ | |
422 stdout_out ("Auto-save? (y or n) "); | |
423 fflush (stdout); | |
424 if (((c = getc (stdin)) & ~040) == 'Y') | |
425 Fdo_auto_save (Qnil, Qnil); | |
426 while (c != '\n') | |
427 c = getc (stdin); | |
428 stdout_out ("Abort (and dump core)? (y or n) "); | |
429 fflush (stdout); | |
430 if (((c = getc (stdin)) & ~040) == 'Y') | |
431 abort (); | |
432 while (c != '\n') | |
433 c = getc (stdin); | |
434 stdout_out ("Continuing...\n"); | |
435 fflush (stdout); | |
436 reinit_initial_console (); | |
437 MARK_FRAME_CHANGED (XFRAME (DEVICE_SELECTED_FRAME | |
438 (XDEVICE (CONSOLE_SELECTED_DEVICE | |
439 (XCONSOLE | |
440 (Vcontrolling_terminal)))))); | |
441 } | |
442 else | |
443 #endif /* ! (defined (ERROR_CHECKING) && defined (MACROIZE_ERROR_CHECKING)) */ | |
444 { | |
445 /* Else request quit when it's safe */ | |
446 Vquit_flag = Qt; | |
447 sigint_happened = 1; | |
448 #ifdef HAVE_UNIXOID_EVENT_LOOP | |
449 signal_fake_event (); | |
450 #endif | |
451 } | |
452 errno = old_errno; | |
453 SIGRETURN; | |
454 } | |
455 | |
456 static Lisp_Object | |
457 restore_dont_check_for_quit (Lisp_Object val) | |
458 { | |
459 dont_check_for_quit = XINT (val); | |
460 return Qnil; | |
461 } | |
462 | |
463 void | |
464 begin_dont_check_for_quit (void) | |
465 { | |
466 specbind (Qinhibit_quit, Qt); | |
467 record_unwind_protect (restore_dont_check_for_quit, | |
468 make_int (dont_check_for_quit)); | |
469 dont_check_for_quit = 1; | |
470 } | |
471 | |
472 /* The effect of this function is to set Vquit_flag if the user pressed | |
473 ^G and discard the ^G, so as to not notice the same ^G again. */ | |
474 int | |
475 check_quit (void) | |
476 { | |
477 /* dont_check_for_quit is set in two circumstances: | |
478 | |
479 (1) when we are in the process of changing the window | |
480 configuration. The frame might be in an inconsistent state, | |
481 which will cause assertion failures if we check for QUIT. | |
482 | |
483 (2) when we are reading events, and want to read the C-g | |
484 as an event. The normal check for quit will discard the C-g, | |
485 which would be bad. | |
486 | |
487 #### C-g is still often read as quit, e.g. if you type C-x C-g | |
488 (the C-g happens during the sit-for in maybe_echo_keys(); even | |
489 if we attempt to inhibit quit here, there is still a check | |
490 later on for QUIT. To fix this properly requires a fairly | |
491 substantial overhaul of the quit-checking code, which is | |
492 probably not worth it.) | |
493 | |
494 We should *not* conditionalize on Vinhibit_quit, or | |
495 critical-quit (Control-Shift-G) won't work right. */ | |
496 | |
497 if (dont_check_for_quit) | |
498 return 0; | |
499 | |
500 if (quit_check_signal_happened) | |
501 { | |
502 quit_check_signal_happened = 0; | |
503 event_stream_quit_p (); | |
504 return 1; | |
505 } | |
506 else | |
507 return 0; | |
508 } | |
509 | |
510 int | |
511 check_what_happened (void) /* called from QUIT when | |
512 something_happened gets set */ | |
513 { | |
514 something_happened = 0; | |
515 if (alarm_happened) | |
516 { | |
517 alarm_happened = 0; | |
518 handle_alarm_going_off (); | |
519 } | |
520 return check_quit (); | |
521 } | |
522 | |
523 | |
524 | |
525 void | |
526 init_poll_for_quit (void) | |
527 { | |
528 #if !defined (SIGIO) && !defined (DONT_POLL_FOR_QUIT) | |
529 /* Check for C-g every 1/4 of a second. | |
530 | |
531 #### This is just a guess. Some investigation will have to be | |
532 done to see what the best value is. The best value is the | |
533 smallest possible value that doesn't cause a significant amount | |
534 of running time to be spent in C-g checking. */ | |
535 if (!poll_for_quit_id) | |
536 poll_for_quit_id = | |
537 event_stream_generate_wakeup (NORMAL_QUIT_CHECK_TIMEOUT_MSECS, | |
538 NORMAL_QUIT_CHECK_TIMEOUT_MSECS, | |
539 Qnil, Qnil, 1); | |
540 #endif /* not SIGIO and not DONT_POLL_FOR_QUIT */ | |
541 } | |
542 | |
543 void | |
544 reset_poll_for_quit (void) | |
545 { | |
546 #if !defined (SIGIO) && !defined (DONT_POLL_FOR_QUIT) | |
547 if (poll_for_quit_id) | |
548 { | |
549 event_stream_disable_wakeup (poll_for_quit_id, 1); | |
550 poll_for_quit_id = 0; | |
551 } | |
552 #endif /* not SIGIO and not DONT_POLL_FOR_QUIT */ | |
553 } | |
554 | |
555 #if defined(HAVE_UNIX_PROCESSES) && !defined(SIGCHLD) | |
556 | |
557 static void | |
558 init_poll_for_sigchld (void) | |
559 { | |
560 /* Check for terminated processes every 1/4 of a second. | |
561 | |
562 #### This is just a guess. Some investigation will have to be | |
563 done to see what the best value is. The best value is the | |
564 smallest possible value that doesn't cause a significant amount | |
565 of running time to be spent in process-termination checking. | |
566 */ | |
567 poll_for_sigchld_id = | |
568 event_stream_generate_wakeup (NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS, | |
569 NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS, | |
570 Qnil, Qnil, 1); | |
571 } | |
572 | |
573 #endif /* not SIGCHLD */ | |
574 | |
575 #ifdef SIGIO | |
576 | |
577 static void | |
578 input_available_signal (int signo) | |
579 { | |
580 something_happened = 1; /* tell QUIT to wake up */ | |
581 quit_check_signal_happened = 1; | |
582 quit_check_signal_tick_count++; | |
583 EMACS_REESTABLISH_SIGNAL (signo, input_available_signal); | |
584 SIGRETURN; | |
585 } | |
586 | |
587 #endif /* SIGIO */ | |
588 | |
589 | |
590 /**********************************************************************/ | |
591 /* Enabling/disabling signals */ | |
592 /**********************************************************************/ | |
593 | |
594 static int interrupts_initted; | |
595 | |
596 void | |
597 stop_interrupts (void) | |
598 { | |
599 if (!interrupts_initted) | |
600 return; | |
601 #if defined(SIGIO) && !defined(BROKEN_SIGIO) | |
602 unrequest_sigio (); | |
603 #endif | |
604 stop_async_timeouts (); | |
605 } | |
606 | |
607 void | |
608 start_interrupts (void) | |
609 { | |
610 if (!interrupts_initted) | |
611 return; | |
612 #if defined(SIGIO) && !defined(BROKEN_SIGIO) | |
613 request_sigio (); | |
614 #endif | |
615 start_async_timeouts (); | |
616 } | |
617 | |
618 /* Cheesy but workable implementation of sleep() that doesn't | |
619 interfere with our periodic timers. */ | |
620 | |
621 void | |
622 emacs_sleep (int secs) | |
623 { | |
624 stop_interrupts (); | |
625 sleep (secs); | |
626 start_interrupts (); | |
627 } | |
628 | |
629 | |
630 /************************************************************************/ | |
631 /* initialization */ | |
632 /************************************************************************/ | |
633 | |
634 /* If we've been nohup'ed, keep it that way. | |
635 This allows `nohup xemacs &' to work. | |
636 More generally, if a normally fatal signal has been redirected | |
637 to SIG_IGN by our invocation environment, trust the environment. | |
638 This keeps xemacs from being killed by a SIGQUIT intended for a | |
639 different process after having been backgrounded under a | |
640 non-job-control shell! */ | |
641 static void | |
642 handle_signal_if_fatal (int signo) | |
643 { | |
644 if (signal (signo, fatal_error_signal) == SIG_IGN) | |
645 signal (signo, SIG_IGN); | |
646 } | |
647 | |
648 void | |
649 init_signals_very_early (void) | |
650 { | |
651 /* Catch all signals that would kill us. | |
652 Don't catch these signals in batch mode if not initialized. | |
653 On some machines, this sets static data that would make | |
654 signal fail to work right when the dumped Emacs is run. */ | |
655 if (noninteractive && !initialized) | |
656 return; | |
657 | |
658 handle_signal_if_fatal (SIGILL); /* ANSI */ | |
659 handle_signal_if_fatal (SIGABRT); /* ANSI */ | |
660 handle_signal_if_fatal (SIGFPE); /* ANSI */ | |
661 handle_signal_if_fatal (SIGSEGV); /* ANSI */ | |
662 handle_signal_if_fatal (SIGTERM); /* ANSI */ | |
663 | |
664 | |
665 #ifdef SIGHUP | |
666 handle_signal_if_fatal (SIGHUP); /* POSIX */ | |
667 #endif | |
668 #ifdef SIGQUIT | |
669 handle_signal_if_fatal (SIGQUIT); /* POSIX */ | |
670 #endif | |
671 #ifdef SIGTRAP | |
672 handle_signal_if_fatal (SIGTRAP); /* POSIX */ | |
673 #endif | |
674 #ifdef SIGUSR1 | |
675 handle_signal_if_fatal (SIGUSR1); /* POSIX */ | |
676 #endif | |
677 #ifdef SIGUSR2 | |
678 handle_signal_if_fatal (SIGUSR2); /* POSIX */ | |
679 #endif | |
680 #ifdef SIGPIPE | |
681 handle_signal_if_fatal (SIGPIPE); /* POSIX */ | |
682 #endif | |
683 #ifdef SIGALRM | |
684 /* This will get reset later, once we're | |
685 capable of handling it properly. */ | |
686 handle_signal_if_fatal (SIGALRM); /* POSIX */ | |
687 #endif | |
688 | |
689 | |
690 #ifdef SIGBUS | |
691 handle_signal_if_fatal (SIGBUS); /* XPG5 */ | |
692 #endif | |
693 #ifdef SIGSYS | |
694 handle_signal_if_fatal (SIGSYS); /* XPG5 */ | |
695 #endif | |
696 #ifdef SIGXCPU | |
697 handle_signal_if_fatal (SIGXCPU); /* XPG5 */ | |
698 #endif | |
699 #ifdef SIGXFSZ | |
700 handle_signal_if_fatal (SIGXFSZ); /* XPG5 */ | |
701 #endif | |
702 #ifdef SIGVTALRM | |
703 handle_signal_if_fatal (SIGVTALRM); /* XPG5 */ | |
704 #endif | |
705 #ifdef SIGPROF | |
706 /* Messes up the REAL profiler */ | |
707 /* handle_signal_if_fatal (SIGPROF); */ /* XPG5 */ | |
708 #endif | |
709 | |
710 | |
711 #ifdef SIGHWE | |
712 handle_signal_if_fatal (SIGHWE); | |
713 #endif | |
714 #ifdef SIGPRE | |
715 handle_signal_if_fatal (SIGPRE); | |
716 #endif | |
717 #ifdef SIGORE | |
718 handle_signal_if_fatal (SIGORE); | |
719 #endif | |
720 #ifdef SIGUME | |
721 handle_signal_if_fatal (SIGUME); | |
722 #endif | |
723 #ifdef SIGDLK | |
724 handle_signal_if_fatal (SIGDLK); | |
725 #endif | |
726 #ifdef SIGCPULIM | |
727 handle_signal_if_fatal (SIGCPULIM); | |
728 #endif | |
729 #ifdef SIGIOT | |
730 handle_signal_if_fatal (SIGIOT); | |
731 #endif | |
732 #ifdef SIGEMT | |
733 handle_signal_if_fatal (SIGEMT); | |
734 #endif | |
735 #ifdef SIGLOST | |
736 handle_signal_if_fatal (SIGLOST); | |
737 #endif | |
738 #ifdef SIGSTKFLT /* coprocessor stack fault under Linux */ | |
739 handle_signal_if_fatal (SIGSTKFLT); | |
740 #endif | |
741 #ifdef SIGUNUSED /* exists under Linux, and will kill process! */ | |
742 handle_signal_if_fatal (SIGUNUSED); | |
743 #endif | |
744 | |
745 #ifdef AIX | |
746 /* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU. */ | |
747 #ifndef _I386 | |
748 handle_signal_if_fatal (SIGIOINT); | |
749 #endif | |
750 handle_signal_if_fatal (SIGGRANT); | |
751 handle_signal_if_fatal (SIGRETRACT); | |
752 handle_signal_if_fatal (SIGSOUND); | |
753 handle_signal_if_fatal (SIGMSG); | |
754 #endif /* AIX */ | |
755 | |
756 #ifdef SIGDANGER | |
757 /* This just means available memory is getting low. */ | |
758 signal (SIGDANGER, memory_warning_signal); | |
759 #endif | |
760 } | |
761 | |
762 void | |
763 syms_of_signal (void) | |
764 { | |
765 DEFSUBR (Fwaiting_for_user_input_p); | |
766 } | |
767 | |
768 void | |
769 init_interrupts_late (void) | |
770 { | |
771 if (!noninteractive) | |
772 { | |
773 signal (SIGINT, interrupt_signal); | |
774 #ifdef HAVE_TERMIO | |
775 /* On systems with TERMIO, C-g is set up for both SIGINT and SIGQUIT | |
776 and we can't tell which one it will give us. */ | |
777 signal (SIGQUIT, interrupt_signal); | |
778 #endif /* HAVE_TERMIO */ | |
779 init_async_timeouts (); | |
780 #ifdef SIGIO | |
781 signal (SIGIO, input_available_signal); | |
782 # ifdef SIGPOLL /* XPG5 */ | |
783 /* Some systems (e.g. Motorola SVR4) losingly have different | |
784 values for SIGIO and SIGPOLL, and send SIGPOLL instead of | |
785 SIGIO. On those same systems, an uncaught SIGPOLL kills the | |
786 process. */ | |
787 signal (SIGPOLL, input_available_signal); | |
788 # endif | |
789 #elif !defined (DONT_POLL_FOR_QUIT) | |
790 init_poll_for_quit (); | |
791 #endif | |
792 } | |
793 | |
794 #if defined(HAVE_UNIX_PROCESSES) && !defined(SIGCHLD) | |
795 init_poll_for_sigchld (); | |
796 #endif | |
797 | |
798 EMACS_UNBLOCK_ALL_SIGNALS (); | |
799 | |
800 interrupts_initted = 1; | |
801 } | |
802 |