comparison src/signal.c @ 593:5fd7ba8b56e7

[xemacs-hg @ 2001-05-31 12:45:27 by ben] xemacs-faq.texi: Major rewrite. Update all MS Windows info to current. Redo section 6.1 almost completely. Incorporate sections 1 and 2 of Hrvoje's FAQ. etags.el: Fix infloop when going up to the root. s\cygwin32.h: Don't unilaterally include ntplay, but only when we're compiling with native sound (look in configure now). event-msw.c: Fix yet more problems with C-g handling. Implement debug-mswindows-events. event-stream.c, events.h, signal.c, sysdep.h: Rearrange the signal-handling code to eliminate the former spaghetti logic paths in it. Document clearly what "low-level" and "high-level" timeouts are. Rename some functions with unclear names (e.g. "...alarm...") to names that reflect what they actually do (e.g. "...async_timeout..."). Fix numerous bugs discovered in the process. console-x.h, event-Xt.c, event-msw.c, frame-x.c: Hopefully make XEmacs properly maintain the "iconified" state on frames at all times. This should fix the "can't delete a frame with C-x 5 0 when there's another iconified frame out there" bug. Put a notice in of further changes that should probably be made to clean up the frame-visibility support. (especially directed at Jan Vroonhof) lisp.h, miscplay.c: Rename SBufbyte to CBufbyte to avoid a misleading name. Eliminate UChar, which is not used anywhere and contributes no semantic info. Add a comment about the documentation-only properties of the char/unsigned char typedefs. Add SChar_Binary as an explicitly `signed' version of Char_Binary and put back the `signed' declarations in miscplay.c. alloc.c: Use char typedefs. console-msw.c, device-msw.c, dialog-msw.c, editfns.c, fileio.c, glyphs-eimage.c, menubar-msw.c, ntplay.c, objects-msw.c, realpath.c, redisplay-msw.c, select-msw.c, syswindows.h, win32.c: Eliminate numerous C++ errors. frame-msw.c: Eliminate numerous C++ errors and Mule-ize. glyphs-msw.c: Eliminate numerous C++ errors and use char typedefs. configure.in: Fix problems detecting both native and Linux sound on Cygwin when compiled with --with-msw=no. Rearrange file-coding handling a bit to avoid warning when compiling with Mule. configure.in, configure.usage, INSTALL: Document XEMACS_CC and corresponding compiler option --xemacs-compiler. Explain how to build xemacs using a C++ compiler.
author ben
date Thu, 31 May 2001 12:45:41 +0000
parents abe6d1db359e
children 38db05db9cb5
comparison
equal deleted inserted replaced
592:4f6ba8f1fb3d 593:5fd7ba8b56e7
1 /* Handling asynchronous signals. 1 /* Handling asynchronous signals.
2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. 2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
3 Copyright (C) 1995, 1996 Ben Wing. 3 Copyright (C) 1995, 1996, 2001 Ben Wing.
4 4
5 This file is part of XEmacs. 5 This file is part of XEmacs.
6 6
7 XEmacs is free software; you can redistribute it and/or modify it 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 8 under the terms of the GNU General Public License as published by the
25 #include "lisp.h" 25 #include "lisp.h"
26 26
27 #include "console.h" 27 #include "console.h"
28 #include "events.h" /* for signal_fake_event() */ 28 #include "events.h" /* for signal_fake_event() */
29 #include "frame.h" 29 #include "frame.h"
30 #include "process.h"
30 #include "sysdep.h" 31 #include "sysdep.h"
31 #include "syssignal.h" 32 #include "syssignal.h"
32 #include "systime.h" 33 #include "systime.h"
33 34
34 #include "sysfile.h" 35 #include "sysfile.h"
45 /* Set to 1 when a SIGINT (or SIGQUIT) interrupt is processed. 46 /* Set to 1 when a SIGINT (or SIGQUIT) interrupt is processed.
46 maybe_read_quit_event() looks at this. */ 47 maybe_read_quit_event() looks at this. */
47 volatile int sigint_happened; 48 volatile int sigint_happened;
48 49
49 /* Set to 1 when an asynch. timeout signal occurs. */ 50 /* Set to 1 when an asynch. timeout signal occurs. */
50 static volatile int alarm_happened; 51 static volatile int async_timeout_happened;
52
53 /* Set to 1 when a multiple of SLOWED_DOWN_INTERRUPTS_SECS elapses,
54 after slow_down_interrupts() is called. */
55 static volatile int slowed_interrupt_timeout_happened;
51 56
52 /* This is used to synchronize setting the waiting_for_user_input_p 57 /* This is used to synchronize setting the waiting_for_user_input_p
53 flag. */ 58 flag. */
54 static volatile int alarm_happened_while_emacs_was_blocking; 59 static volatile int async_timeout_happened_while_emacs_was_blocking;
55 60
56 /* See check_quit() for when this is set. */ 61 /* See check_quit() for when this is set. */
57 int dont_check_for_quit; 62 int dont_check_for_quit;
58 63
59 #if !defined (SIGIO) && !defined (DONT_POLL_FOR_QUIT) 64 static int poll_for_quit_id;
60 int poll_for_quit_id; 65 static int poll_for_sigchld_id;
61 #endif
62
63 #if defined(HAVE_UNIX_PROCESSES) && !defined(SIGCHLD)
64 int poll_for_sigchld_id;
65 #endif
66 66
67 /* This variable is used to communicate to a lisp 67 /* This variable is used to communicate to a lisp
68 process-filter/sentinel/asynchronous callback (via the function 68 process-filter/sentinel/asynchronous callback (via the function
69 Fwaiting_for_user_input_p below) whether XEmacs was waiting for 69 Fwaiting_for_user_input_p below) whether XEmacs was waiting for
70 user-input when that process-filter was called. */ 70 user-input when that process-filter was called. */
80 naturally interruptible. */ 80 naturally interruptible. */
81 81
82 JMP_BUF break_system_call_jump; 82 JMP_BUF break_system_call_jump;
83 volatile int can_break_system_calls; 83 volatile int can_break_system_calls;
84 84
85 static SIGTYPE alarm_signal (int signo);
86
87
85 88
86 /**********************************************************************/ 89 /**********************************************************************/
87 /* Asynchronous timeout functions */ 90 /* Asynchronous timeout functions */
88 /**********************************************************************/ 91 /**********************************************************************/
92
93 /* See the comment in event-stream.c, under major heading "Timeouts",
94 for the difference between low-level (one-shot) and high-level
95 (periodic/resignaling) timeouts. */
89 96
90 /* The pending timers are stored in an ordered list, where the first timer 97 /* The pending timers are stored in an ordered list, where the first timer
91 on the list is the first one to fire. Times recorded here are 98 on the list is the first one to fire. Times recorded here are
92 absolute. */ 99 absolute. */
93 static struct low_level_timeout *async_timer_queue; 100 static struct low_level_timeout *async_timer_queue;
129 EMACS_SET_SECS_USECS (interval, 0, 0); 136 EMACS_SET_SECS_USECS (interval, 0, 0);
130 137
131 set_one_shot_timer (interval); 138 set_one_shot_timer (interval);
132 } 139 }
133 140
141
142 static void
143 init_async_timeouts (void)
144 {
145 signal (SIGALRM, alarm_signal);
146 async_timer_suppress_count = 0;
147 }
148
149 /* Turn off async timeouts. */
150
151 static void
152 stop_async_timeouts (void)
153 {
154 if (async_timer_suppress_count == 0)
155 {
156 /* If timer was on, turn it off. */
157 EMACS_TIME thyme;
158 EMACS_SET_SECS_USECS (thyme, 0, 0);
159 set_one_shot_timer (thyme);
160 }
161 async_timer_suppress_count++;
162 }
163
164 /* Turn on async timeouts again. */
165
166 static void
167 start_async_timeouts (void)
168 {
169 assert (async_timer_suppress_count > 0);
170 async_timer_suppress_count--;
171 if (async_timer_suppress_count == 0)
172 {
173 /* Some callers turn off async timeouts and then use the alarm
174 for their own purposes; so reinitialize everything. */
175 signal (SIGALRM, alarm_signal);
176 reset_interval_timer ();
177 }
178 }
179
180 static void
181 handle_async_timeout_signal (void)
182 {
183 int interval_id;
184 int wakeup_id;
185 Lisp_Object fun, arg;
186
187 /* No checks for Vinhibit_quit here or anywhere else in this file!!!
188 Otherwise critical quit will not work right.
189 The only check for Vinhibit_quit is in QUIT itself. */
190 interval_id = pop_low_level_timeout (&async_timer_queue, 0);
191
192 reset_interval_timer ();
193 if (async_timeout_happened_while_emacs_was_blocking)
194 {
195 async_timeout_happened_while_emacs_was_blocking = 0;
196 waiting_for_user_input_p = 1;
197 }
198
199 wakeup_id = event_stream_resignal_wakeup (interval_id, 1, &fun, &arg);
200
201 if (wakeup_id == poll_for_quit_id)
202 {
203 quit_check_signal_happened = 1;
204 quit_check_signal_tick_count++;
205 }
206 else if (wakeup_id == poll_for_sigchld_id)
207 {
208 kick_status_notify ();
209 }
210 else
211 /* call1 GC-protects its arguments */
212 call1_trapping_errors ("Error in asynchronous timeout callback",
213 fun, arg);
214
215 waiting_for_user_input_p = 0;
216 }
217
218 /* The following two functions are the external interface onto
219 creating/deleting asynchronous interval timeouts, and are
220 called by event-stream.c. We call back to event-stream.c using
221 event_stream_resignal_wakeup(), when an interval goes off. */
222
134 int 223 int
135 event_stream_add_async_timeout (EMACS_TIME thyme) 224 signal_add_async_interval_timeout (EMACS_TIME thyme)
136 { 225 {
137 int id = add_low_level_timeout (&async_timer_queue, thyme); 226 int id = add_low_level_timeout (&async_timer_queue, thyme);
138 227
139 /* If this timeout is at the head of the queue, then we need to 228 /* If this timeout is at the head of the queue, then we need to
140 set the timer right now for this timeout. Otherwise, things 229 set the timer right now for this timeout. Otherwise, things
146 235
147 return id; 236 return id;
148 } 237 }
149 238
150 void 239 void
151 event_stream_remove_async_timeout (int id) 240 signal_remove_async_interval_timeout (int id)
152 { 241 {
153 int first = (async_timer_queue && async_timer_queue->id == id); 242 int first = (async_timer_queue && async_timer_queue->id == id);
154 remove_low_level_timeout (&async_timer_queue, id); 243 remove_low_level_timeout (&async_timer_queue, id);
155 244
156 /* If we removed the timeout from the head of the queue, then 245 /* If we removed the timeout from the head of the queue, then
157 we need to reset the interval timer right now. */ 246 we need to reset the interval timer right now. */
158 if (first) 247 if (first)
159 reset_interval_timer (); 248 reset_interval_timer ();
160 } 249 }
161 250
162 /* Handle an alarm once each second and read pending input 251 /* If alarm() gets called when polling isn't disabled, it will mess up
163 so as to handle a C-g if it comes in. */ 252 the asynchronous timeouts, and then C-g checking won't work again.
164 253 Some libraries call alarm() directly, so we override the standard
165 static SIGTYPE 254 library's alarm() and abort() if the caller of the library function
166 alarm_signal (int signo) 255 didn't wrap in stop_interrupts()/start_interrupts().
167 { 256
168 if (interrupts_slowed_down) 257 NOTE: We could potentially avoid the need to wrap by adding a
169 { 258 one-shot timeout to simulate the alarm(), smashing our signal
170 something_happened = 1; /* tell QUIT to wake up */ 259 handler back into place, and calling the library function when the
171 /* we are in "slowed-down interrupts" mode; the only alarm 260 alarm goes off. But do we want to? We're not going to gain the
172 happening here is the slowed-down quit-check alarm, so 261 ability to C-g out of library functions this way (unless we forcibly
173 we set this flag. 262 longjmp() out of a signal handler, which is likely to lead to a
174 263 crash). --ben */
175 Do NOT set alarm_happened, because we don't want anyone 264
176 looking at the timeout queue. We didn't set it and 265 #ifdef HAVE_SETITIMER
177 it needs to stay the way it is. */ 266 unsigned int
178 quit_check_signal_happened = 1; 267 alarm (unsigned int howlong)
179 268 {
180 #ifdef WIN32_NATIVE 269 struct itimerval old_it, new_it;
181 can_break_system_calls = 0; 270
182 #else
183 /* can_break_system_calls is set when we want to break out of
184 non-interruptible system calls. */
185 if (can_break_system_calls)
186 {
187 /* reset the flag for safety and such. Do this *before*
188 unblocking or reestablishing the signal to avoid potential
189 race conditions. */
190 can_break_system_calls = 0;
191 EMACS_UNBLOCK_SIGNAL (signo);
192 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal);
193 LONGJMP (break_system_call_jump, 0);
194 }
195 #endif
196
197 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal);
198 SIGRETURN;
199 }
200
201 something_happened = 1; /* tell QUIT to wake up */
202 alarm_happened = 1;
203 if (emacs_is_blocking)
204 alarm_happened_while_emacs_was_blocking = 1;
205 /* #### This is for QUITP. When it is run, it may not be the
206 place to do arbitrary stuff like run asynch. handlers, but
207 it needs to know whether the poll-for-quit asynch. timeout
208 went off. Rather than put the code in to compute this
209 specially, we just set this flag. Should fix this. */
210 quit_check_signal_happened = 1;
211
212 #ifdef HAVE_UNIXOID_EVENT_LOOP
213 signal_fake_event ();
214 #endif
215
216 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal);
217 SIGRETURN;
218 }
219
220 static void
221 init_async_timeouts (void)
222 {
223 signal (SIGALRM, alarm_signal);
224 async_timer_suppress_count = 0;
225 }
226
227 /* Turn off async timeouts. */
228
229 static void
230 stop_async_timeouts (void)
231 {
232 if (async_timer_suppress_count == 0)
233 {
234 /* If timer was on, turn it off. */
235 EMACS_TIME thyme;
236 EMACS_SET_SECS_USECS (thyme, 0, 0);
237 set_one_shot_timer (thyme);
238 }
239 async_timer_suppress_count++;
240 }
241
242 /* Turn on async timeouts again. */
243
244 static void
245 start_async_timeouts (void)
246 {
247 assert (async_timer_suppress_count > 0); 271 assert (async_timer_suppress_count > 0);
248 async_timer_suppress_count--; 272
249 if (async_timer_suppress_count == 0) 273 new_it.it_value.tv_sec = howlong;
250 { 274 new_it.it_value.tv_usec = 0;
251 /* Some callers turn off async timeouts and then use the alarm 275 new_it.it_interval.tv_sec = 0;
252 for their own purposes; so reinitialize everything. */ 276 new_it.it_interval.tv_usec = 0;
253 signal (SIGALRM, alarm_signal); 277 setitimer (ITIMER_REAL, &new_it, &old_it);
254 reset_interval_timer (); 278
255 } 279 /* Never return zero if there was a timer outstanding. */
280 return old_it.it_value.tv_sec + (old_it.it_value.tv_usec > 0 ? 1 : 0);
281 }
282 #endif
283
284 DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, 0, 0, 0, /*
285 Return non-nil if XEmacs is waiting for input from the user.
286 This is intended for use by asynchronous timeout callbacks and by
287 asynchronous process output filters and sentinels (not yet implemented
288 in XEmacs). It will always be nil if XEmacs is not inside of
289 an asynchronous timeout or process callback.
290 */
291 ())
292 {
293 return waiting_for_user_input_p ? Qt : Qnil;
294 }
295
296
297 /**********************************************************************/
298 /* Enabling/disabling signals */
299 /**********************************************************************/
300
301 static int interrupts_initted;
302
303 void
304 stop_interrupts (void)
305 {
306 if (!interrupts_initted)
307 return;
308 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
309 unrequest_sigio ();
310 #endif
311 stop_async_timeouts ();
312 }
313
314 void
315 start_interrupts (void)
316 {
317 if (!interrupts_initted)
318 return;
319 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
320 request_sigio ();
321 #endif
322 start_async_timeouts ();
323 }
324
325
326 static void
327 establish_slow_interrupt_timer (void)
328 {
329 EMACS_TIME thyme;
330
331 EMACS_SET_SECS_USECS (thyme, SLOWED_DOWN_INTERRUPTS_SECS, 0);
332 set_one_shot_timer (thyme);
256 } 333 }
257 334
258 /* Some functions don't like being interrupted with SIGALRM or SIGIO. 335 /* Some functions don't like being interrupted with SIGALRM or SIGIO.
259 Previously we were calling stop_interrupts() / start_interrupts(), 336 Previously we were calling stop_interrupts() / start_interrupts(),
260 but then if the program hangs in one of those functions, e.g. 337 but then if the program hangs in one of those functions, e.g.
266 interrupt bogus ones. */ 343 interrupt bogus ones. */
267 344
268 void 345 void
269 slow_down_interrupts (void) 346 slow_down_interrupts (void)
270 { 347 {
271 EMACS_TIME thyme;
272
273 /* We have to set the flag *before* setting the slowed-down timer, 348 /* We have to set the flag *before* setting the slowed-down timer,
274 to avoid a race condition -- if the signal occurs between the 349 to avoid a race condition -- if the signal occurs between the
275 call to set_one_shot_timer() and the setting of this flag, 350 call to set_one_shot_timer() and the setting of this flag,
276 alarm_happened will get set, which will be a Bad Thing if 351 async_timeout_happened will get set, which will be a Bad Thing if
277 there were no timeouts on the queue. */ 352 there were no timeouts on the queue. */
278 interrupts_slowed_down++; 353 interrupts_slowed_down++;
279 if (interrupts_slowed_down == 1) 354 if (interrupts_slowed_down == 1)
280 { 355 {
281 stop_interrupts (); 356 stop_interrupts ();
282 EMACS_SET_SECS_USECS (thyme, SLOWED_DOWN_INTERRUPTS_SECS, 0); 357 establish_slow_interrupt_timer ();
283 set_one_shot_timer (thyme);
284 } 358 }
285 } 359 }
286 360
287 void 361 void
288 speed_up_interrupts (void) 362 speed_up_interrupts (void)
294 race-condition reasons as above. */ 368 race-condition reasons as above. */
295 interrupts_slowed_down--; 369 interrupts_slowed_down--;
296 } 370 }
297 } 371 }
298 372
299 static void 373 /* Cheesy but workable implementation of sleep() that doesn't
300 handle_alarm_going_off (void) 374 interfere with our periodic timers. */
301 { 375
302 int interval_id; 376 void
303 377 emacs_sleep (int secs)
304 /* If asynch. timeouts are blocked, then don't do anything now, 378 {
305 but make this function get called again next QUIT. 379 stop_interrupts ();
306 380 sleep (secs);
307 #### This is a bit inefficient because there will be function call 381 start_interrupts ();
308 overhead each time QUIT occurs. */
309
310 if (!NILP (Vinhibit_quit))
311 {
312 something_happened = 1;
313 alarm_happened = 1;
314 return;
315 }
316
317 interval_id = pop_low_level_timeout (&async_timer_queue, 0);
318
319 reset_interval_timer ();
320 if (alarm_happened_while_emacs_was_blocking)
321 {
322 alarm_happened_while_emacs_was_blocking = 0;
323 waiting_for_user_input_p = 1;
324 }
325 event_stream_deal_with_async_timeout (interval_id);
326 waiting_for_user_input_p = 0;
327 }
328
329 #ifdef HAVE_SETITIMER
330 unsigned int
331 alarm (unsigned int howlong)
332 {
333 struct itimerval old_it, new_it;
334
335 /* If alarm() gets called when polling isn't disabled, it can mess
336 up the periodic timer. */
337 assert (async_timer_suppress_count > 0);
338
339 new_it.it_value.tv_sec = howlong;
340 new_it.it_value.tv_usec = 0;
341 new_it.it_interval.tv_sec = 0;
342 new_it.it_interval.tv_usec = 0;
343 setitimer (ITIMER_REAL, &new_it, &old_it);
344
345 /* Never return zero if there was a timer outstanding. */
346 return old_it.it_value.tv_sec + (old_it.it_value.tv_usec > 0 ? 1 : 0);
347 }
348 #endif
349
350 DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, 0, 0, 0, /*
351 Return non-nil if XEmacs is waiting for input from the user.
352 This is intended for use by asynchronous timeout callbacks and by
353 asynchronous process output filters and sentinels (not yet implemented
354 in XEmacs). It will always be nil if XEmacs is not inside of
355 an asynchronous timeout or process callback.
356 */
357 ())
358 {
359 return waiting_for_user_input_p ? Qt : Qnil;
360 } 382 }
361 383
362 384
363 /**********************************************************************/ 385 /**********************************************************************/
364 /* Control-G checking */ 386 /* The mechanism that drives it all */
365 /**********************************************************************/ 387 /**********************************************************************/
388
389 /* called from QUIT when something_happened gets set (as a result of
390 a signal) */
391
392 int
393 check_what_happened (void)
394 {
395 something_happened = 0;
396 if (async_timeout_happened)
397 {
398 async_timeout_happened = 0;
399 handle_async_timeout_signal ();
400 }
401 if (slowed_interrupt_timeout_happened)
402 {
403 slowed_interrupt_timeout_happened = 0;
404 establish_slow_interrupt_timer ();
405 }
406
407 return check_quit ();
408 }
409
410 #ifdef SIGIO
411
412 /* Signal handler for SIGIO. */
413
414 static void
415 input_available_signal (int signo)
416 {
417 something_happened = 1; /* tell QUIT to wake up */
418 quit_check_signal_happened = 1;
419 quit_check_signal_tick_count++;
420 EMACS_REESTABLISH_SIGNAL (signo, input_available_signal);
421 SIGRETURN;
422 }
423
424 #endif /* SIGIO */
425
426 /* Actual signal handler for SIGALRM. Called when:
427
428 -- asynchronous timeouts (added with `add-async-timeout') go off
429
430 -- when the poll-for-quit timer (used for C-g handling; more or
431 less when SIGIO is unavailable or BROKEN_SIGIO is defined) or
432 poll-for-sigchld timer (used when BROKEN_SIGCHLD is defined) go
433 off. The latter two timers, if set, normally go off every 1/4
434 of a second -- see NORMAL_QUIT_CHECK_TIMEOUT_MSECS and
435 NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS. (Both of these timers are
436 treated like other asynchronous timeouts, but special-cased
437 in handle_async_timeout_signal().)
438
439 -- we called slow_down_interrupts() and SLOWED_DOWN_INTERRUPTS_SECS
440 (or a multiple of it) has elapsed.
441
442 Note that under Windows, we have no working setitimer(), so we
443 simulate it using the multimedia timeout functions,
444 e.g. timeSetEvent(). See setitimer() in nt.c.
445
446 Note also that we don't actually *do* anything here (except in the
447 case of can_break_system_calls). Instead, we just set various
448 flags; next time QUIT is called, the flags will cause
449 check_what_happened() to be called, at which point we do everything
450 indicated by the flags.
451 */
452
453 static SIGTYPE
454 alarm_signal (int signo)
455 {
456 something_happened = 1; /* tell QUIT to wake up and call
457 check_what_happened() */
458
459 if (interrupts_slowed_down)
460 {
461 /* we are in "slowed-down interrupts" mode; the only alarm
462 happening here is the slowed-down quit-check alarm, so
463 we set this flag.
464
465 Do NOT set async_timeout_happened, because we don't want
466 anyone looking at the timeout queue -- async timeouts
467 are disabled. */
468 quit_check_signal_happened = 1;
469 quit_check_signal_tick_count++;
470 /* make sure we establish the slow timer again. */
471 slowed_interrupt_timeout_happened = 1;
472
473 /* can_break_system_calls is set when we want to break out of
474 non-interruptible system calls. */
475 if (can_break_system_calls)
476 {
477 /* reset the flag for safety and such. Do this *before*
478 unblocking or reestablishing the signal to avoid potential
479 race conditions. */
480 can_break_system_calls = 0;
481 #ifndef WIN32_NATIVE
482 /* #### I didn't add this WIN32_NATIVE check. I'm not sure
483 why it's here. But then again, someone needs to review
484 this can_break_system_calls stuff and see if it still
485 makes sense. --ben */
486 EMACS_UNBLOCK_SIGNAL (signo);
487 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal);
488 LONGJMP (break_system_call_jump, 0);
489 #endif
490 }
491 }
492 else
493 {
494 async_timeout_happened = 1;
495 if (emacs_is_blocking)
496 async_timeout_happened_while_emacs_was_blocking = 1;
497 /* #### This is for QUITP. When it is run, it may not be the
498 place to do arbitrary stuff like run asynch. handlers, but
499 it needs to know whether the poll-for-quit asynch. timeout
500 went off. Rather than put the code in to compute this
501 specially, we just set this flag. Should fix this. */
502 quit_check_signal_happened = 1;
503
504 #ifdef HAVE_UNIXOID_EVENT_LOOP
505 signal_fake_event ();
506 #endif
507 }
508
509 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal);
510 SIGRETURN;
511 }
366 512
367 /* Set this for debugging, to have a way to get out */ 513 /* Set this for debugging, to have a way to get out */
368 int stop_character; /* #### not currently implemented */ 514 int stop_character; /* #### not currently implemented */
369 515
370 /* This routine is called in response to a SIGINT or SIGQUIT. 516 /* Signal handler for SIGINT and SIGQUIT. On TTY's, one of these two
371 On TTY's, one of these two signals will get generated in response 517 signals will get generated in response to C-g. (When running under
372 to C-g. (When running under X, C-g is handled using the SIGIO 518 X, C-g is handled using the SIGIO handler, which sets a flag
373 handler, which sets a flag telling the QUIT macro to scan the 519 telling the QUIT macro to scan the unread events for a ^G.)
374 unread events for a ^G.) 520 */
375
376 Otherwise it sets the Lisp variable quit-flag not-nil.
377 This causes eval to throw, when it gets a chance.
378 If quit-flag is already non-nil, it stops the job right away. */
379 521
380 static SIGTYPE 522 static SIGTYPE
381 interrupt_signal (int sig) 523 interrupt_signal (int sig)
382 { 524 {
383 /* This function can call lisp */ 525 /* This function can call lisp */
386 /* Must preserve main program's value of errno. */ 528 /* Must preserve main program's value of errno. */
387 int old_errno = errno; 529 int old_errno = errno;
388 530
389 EMACS_REESTABLISH_SIGNAL (sig, interrupt_signal); 531 EMACS_REESTABLISH_SIGNAL (sig, interrupt_signal);
390 532
391 /* with the macroized error-checking stuff, the garbage below
392 may mess things up because XCONSOLE() and such can use and
393 change global vars. */
394 #if ! (defined (ERROR_CHECK_TYPECHECK) && defined (MACROIZE_ERROR_CHECKING))
395 if (sigint_happened && CONSOLEP (Vcontrolling_terminal) && 533 if (sigint_happened && CONSOLEP (Vcontrolling_terminal) &&
396 CONSOLE_LIVE_P (XCONSOLE (Vcontrolling_terminal)) && 534 CONSOLE_LIVE_P (XCONSOLE (Vcontrolling_terminal)) &&
397 !emacs_is_blocking) 535 !emacs_is_blocking)
398 { 536 {
537 /* #### this is inherited from GNU Emacs. Do we really want this?
538 --ben */
399 char c; 539 char c;
400 fflush (stdout); 540 fflush (stdout);
401 reset_initial_console (); 541 reset_initial_console ();
402 EMACS_UNBLOCK_SIGNAL (sig); 542 EMACS_UNBLOCK_SIGNAL (sig);
403 #ifdef SIGTSTP /* Support possible in later USG versions */ 543 #ifdef SIGTSTP /* Support possible in later USG versions */
432 (XDEVICE (CONSOLE_SELECTED_DEVICE 572 (XDEVICE (CONSOLE_SELECTED_DEVICE
433 (XCONSOLE 573 (XCONSOLE
434 (Vcontrolling_terminal)))))); 574 (Vcontrolling_terminal))))));
435 } 575 }
436 else 576 else
437 #endif /* ! (defined (ERROR_CHECKING) && defined (MACROIZE_ERROR_CHECKING)) */
438 { 577 {
439 /* Else request quit when it's safe */ 578 /* Else request quit when it's safe */
440 Vquit_flag = Qt; 579 Vquit_flag = Qt;
441 sigint_happened = 1; 580 sigint_happened = 1;
442 #ifdef HAVE_UNIXOID_EVENT_LOOP 581 #ifdef HAVE_UNIXOID_EVENT_LOOP
444 #endif 583 #endif
445 } 584 }
446 errno = old_errno; 585 errno = old_errno;
447 SIGRETURN; 586 SIGRETURN;
448 } 587 }
588
589
590 /**********************************************************************/
591 /* Control-G checking */
592 /**********************************************************************/
449 593
450 static Lisp_Object 594 static Lisp_Object
451 restore_dont_check_for_quit (Lisp_Object val) 595 restore_dont_check_for_quit (Lisp_Object val)
452 { 596 {
453 dont_check_for_quit = XINT (val); 597 dont_check_for_quit = XINT (val);
497 event_stream_quit_p (); 641 event_stream_quit_p ();
498 return 1; 642 return 1;
499 } 643 }
500 else 644 else
501 return 0; 645 return 0;
502 }
503
504 int
505 check_what_happened (void) /* called from QUIT when
506 something_happened gets set */
507 {
508 something_happened = 0;
509 if (alarm_happened)
510 {
511 alarm_happened = 0;
512 handle_alarm_going_off ();
513 }
514 return check_quit ();
515 } 646 }
516 647
517 648
518 649
519 void 650 void
532 NORMAL_QUIT_CHECK_TIMEOUT_MSECS, 663 NORMAL_QUIT_CHECK_TIMEOUT_MSECS,
533 Qnil, Qnil, 1); 664 Qnil, Qnil, 1);
534 #endif /* not SIGIO and not DONT_POLL_FOR_QUIT */ 665 #endif /* not SIGIO and not DONT_POLL_FOR_QUIT */
535 } 666 }
536 667
668 #if 0 /* not used anywhere */
669
537 void 670 void
538 reset_poll_for_quit (void) 671 reset_poll_for_quit (void)
539 { 672 {
540 #if !defined (SIGIO) && !defined (DONT_POLL_FOR_QUIT) 673 #if !defined (SIGIO) && !defined (DONT_POLL_FOR_QUIT)
541 if (poll_for_quit_id) 674 if (poll_for_quit_id)
543 event_stream_disable_wakeup (poll_for_quit_id, 1); 676 event_stream_disable_wakeup (poll_for_quit_id, 1);
544 poll_for_quit_id = 0; 677 poll_for_quit_id = 0;
545 } 678 }
546 #endif /* not SIGIO and not DONT_POLL_FOR_QUIT */ 679 #endif /* not SIGIO and not DONT_POLL_FOR_QUIT */
547 } 680 }
681
682 #endif /* 0 */
548 683
549 #if defined(HAVE_UNIX_PROCESSES) && !defined(SIGCHLD) 684 #if defined(HAVE_UNIX_PROCESSES) && !defined(SIGCHLD)
550 685
551 static void 686 static void
552 init_poll_for_sigchld (void) 687 init_poll_for_sigchld (void)
563 NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS, 698 NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS,
564 Qnil, Qnil, 1); 699 Qnil, Qnil, 1);
565 } 700 }
566 701
567 #endif /* not SIGCHLD */ 702 #endif /* not SIGCHLD */
568
569 #ifdef SIGIO
570
571 static void
572 input_available_signal (int signo)
573 {
574 something_happened = 1; /* tell QUIT to wake up */
575 quit_check_signal_happened = 1;
576 quit_check_signal_tick_count++;
577 EMACS_REESTABLISH_SIGNAL (signo, input_available_signal);
578 SIGRETURN;
579 }
580
581 #endif /* SIGIO */
582
583
584 /**********************************************************************/
585 /* Enabling/disabling signals */
586 /**********************************************************************/
587
588 static int interrupts_initted;
589
590 void
591 stop_interrupts (void)
592 {
593 if (!interrupts_initted)
594 return;
595 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
596 unrequest_sigio ();
597 #endif
598 stop_async_timeouts ();
599 }
600
601 void
602 start_interrupts (void)
603 {
604 if (!interrupts_initted)
605 return;
606 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
607 request_sigio ();
608 #endif
609 start_async_timeouts ();
610 }
611
612 /* Cheesy but workable implementation of sleep() that doesn't
613 interfere with our periodic timers. */
614
615 void
616 emacs_sleep (int secs)
617 {
618 stop_interrupts ();
619 sleep (secs);
620 start_interrupts ();
621 }
622 703
623 704
624 /************************************************************************/ 705 /************************************************************************/
625 /* initialization */ 706 /* initialization */
626 /************************************************************************/ 707 /************************************************************************/