428
+ − 1 /* Handling asynchronous signals.
+ − 2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
853
+ − 3 Copyright (C) 1995, 1996, 2001, 2002 Ben Wing.
428
+ − 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"
872
+ − 28 #include "device-impl.h"
428
+ − 29 #include "events.h" /* for signal_fake_event() */
872
+ − 30 #include "frame-impl.h"
593
+ − 31 #include "process.h"
611
+ − 32
428
+ − 33 #include "sysdep.h"
611
+ − 34 #include "sysfile.h"
428
+ − 35 #include "syssignal.h"
+ − 36 #include "systime.h"
+ − 37
+ − 38 /* Set to 1 when a quit-check signal (either a SIGIO interrupt or
+ − 39 the asynch. timeout for poll-for-quit) occurs. The QUITP
+ − 40 macro may look at this. */
+ − 41 volatile int quit_check_signal_happened;
+ − 42
+ − 43 /* Count of the number of times a quit-check signal has occurred.
+ − 44 Some stuff in event-Xt.c looks at this. */
+ − 45 volatile int quit_check_signal_tick_count;
+ − 46
+ − 47 /* Set to 1 when a SIGINT (or SIGQUIT) interrupt is processed.
+ − 48 maybe_read_quit_event() looks at this. */
+ − 49 volatile int sigint_happened;
+ − 50
+ − 51 /* Set to 1 when an asynch. timeout signal occurs. */
593
+ − 52 static volatile int async_timeout_happened;
+ − 53
+ − 54 /* Set to 1 when a multiple of SLOWED_DOWN_INTERRUPTS_SECS elapses,
+ − 55 after slow_down_interrupts() is called. */
+ − 56 static volatile int slowed_interrupt_timeout_happened;
428
+ − 57
+ − 58 /* This is used to synchronize setting the waiting_for_user_input_p
+ − 59 flag. */
593
+ − 60 static volatile int async_timeout_happened_while_emacs_was_blocking;
428
+ − 61
+ − 62 /* See check_quit() for when this is set. */
+ − 63 int dont_check_for_quit;
+ − 64
593
+ − 65 static int poll_for_quit_id;
+ − 66 static int poll_for_sigchld_id;
428
+ − 67
+ − 68 /* This variable is used to communicate to a lisp
+ − 69 process-filter/sentinel/asynchronous callback (via the function
+ − 70 Fwaiting_for_user_input_p below) whether XEmacs was waiting for
+ − 71 user-input when that process-filter was called. */
+ − 72 static int waiting_for_user_input_p;
+ − 73
+ − 74 static int interrupts_slowed_down;
+ − 75
+ − 76 #define SLOWED_DOWN_INTERRUPTS_SECS 15
+ − 77 #define NORMAL_QUIT_CHECK_TIMEOUT_MSECS 250
+ − 78 #define NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS 250
+ − 79
+ − 80 /* Used so that signals can break out of system calls that aren't
+ − 81 naturally interruptible. */
+ − 82
+ − 83 JMP_BUF break_system_call_jump;
+ − 84 volatile int can_break_system_calls;
+ − 85
593
+ − 86 static SIGTYPE alarm_signal (int signo);
+ − 87
+ − 88
428
+ − 89
+ − 90 /**********************************************************************/
+ − 91 /* Asynchronous timeout functions */
+ − 92 /**********************************************************************/
+ − 93
593
+ − 94 /* See the comment in event-stream.c, under major heading "Timeouts",
+ − 95 for the difference between low-level (one-shot) and high-level
+ − 96 (periodic/resignaling) timeouts. */
+ − 97
428
+ − 98 /* The pending timers are stored in an ordered list, where the first timer
+ − 99 on the list is the first one to fire. Times recorded here are
+ − 100 absolute. */
+ − 101 static struct low_level_timeout *async_timer_queue;
+ − 102
+ − 103 /* Nonzero means async timers are temporarily suppressed. */
+ − 104 static int async_timer_suppress_count;
+ − 105
+ − 106 static void
+ − 107 set_one_shot_timer (EMACS_TIME interval)
+ − 108 {
+ − 109 #ifdef HAVE_SETITIMER
+ − 110 struct itimerval it;
+ − 111 it.it_value = interval;
+ − 112 EMACS_SET_SECS_USECS (it.it_interval, 0, 0);
611
+ − 113 qxe_setitimer (ITIMER_REAL, &it, 0);
428
+ − 114 #else
+ − 115 int secs;
+ − 116 EMACS_TIME_TO_INT (interval, secs);
+ − 117 alarm (secs);
+ − 118 #endif
+ − 119 }
+ − 120
+ − 121 static void
+ − 122 reset_interval_timer (void)
+ − 123 {
+ − 124 EMACS_TIME interval;
+ − 125
+ − 126 /* Get the interval to set. If an interval is available,
+ − 127 make sure it's not zero (this is a valid return, but it will
+ − 128 cause the timer to get disabled, so convert it to a very short
+ − 129 time). */
+ − 130 if (get_low_level_timeout_interval (async_timer_queue, &interval))
+ − 131 {
+ − 132 if (EMACS_SECS (interval) == 0 && EMACS_USECS (interval) == 0)
+ − 133 EMACS_SET_USECS (interval, 1);
+ − 134 }
+ − 135 else
+ − 136 /* A time of 0 means "disable". */
+ − 137 EMACS_SET_SECS_USECS (interval, 0, 0);
+ − 138
+ − 139 set_one_shot_timer (interval);
+ − 140 }
+ − 141
+ − 142
+ − 143 static void
+ − 144 init_async_timeouts (void)
+ − 145 {
613
+ − 146 set_timeout_signal (SIGALRM, alarm_signal);
428
+ − 147 async_timer_suppress_count = 0;
+ − 148 }
+ − 149
+ − 150 /* Turn off async timeouts. */
+ − 151
+ − 152 static void
+ − 153 stop_async_timeouts (void)
+ − 154 {
+ − 155 if (async_timer_suppress_count == 0)
+ − 156 {
+ − 157 /* If timer was on, turn it off. */
+ − 158 EMACS_TIME thyme;
+ − 159 EMACS_SET_SECS_USECS (thyme, 0, 0);
+ − 160 set_one_shot_timer (thyme);
+ − 161 }
+ − 162 async_timer_suppress_count++;
+ − 163 }
+ − 164
+ − 165 /* Turn on async timeouts again. */
+ − 166
+ − 167 static void
+ − 168 start_async_timeouts (void)
+ − 169 {
+ − 170 assert (async_timer_suppress_count > 0);
+ − 171 async_timer_suppress_count--;
+ − 172 if (async_timer_suppress_count == 0)
+ − 173 {
+ − 174 /* Some callers turn off async timeouts and then use the alarm
+ − 175 for their own purposes; so reinitialize everything. */
613
+ − 176 set_timeout_signal (SIGALRM, alarm_signal);
428
+ − 177 reset_interval_timer ();
+ − 178 }
+ − 179 }
+ − 180
593
+ − 181 static void
+ − 182 handle_async_timeout_signal (void)
428
+ − 183 {
593
+ − 184 int interval_id;
+ − 185 int wakeup_id;
+ − 186 Lisp_Object fun, arg;
771
+ − 187 /* Avoid any possibility of GC during QUIT */
+ − 188 int specco = begin_gc_forbidden ();
593
+ − 189
+ − 190 /* No checks for Vinhibit_quit here or anywhere else in this file!!!
+ − 191 Otherwise critical quit will not work right.
771
+ − 192 The only check for Vinhibit_quit is in QUIT itself.
+ − 193
+ − 194 (#### ???? I don't quite understand this comment.) */
593
+ − 195 interval_id = pop_low_level_timeout (&async_timer_queue, 0);
+ − 196
+ − 197 reset_interval_timer ();
+ − 198 if (async_timeout_happened_while_emacs_was_blocking)
+ − 199 {
+ − 200 async_timeout_happened_while_emacs_was_blocking = 0;
+ − 201 waiting_for_user_input_p = 1;
+ − 202 }
+ − 203
+ − 204 wakeup_id = event_stream_resignal_wakeup (interval_id, 1, &fun, &arg);
428
+ − 205
593
+ − 206 if (wakeup_id == poll_for_quit_id)
+ − 207 {
+ − 208 quit_check_signal_happened = 1;
+ − 209 quit_check_signal_tick_count++;
+ − 210 }
+ − 211 else if (wakeup_id == poll_for_sigchld_id)
428
+ − 212 {
593
+ − 213 kick_status_notify ();
428
+ − 214 }
593
+ − 215 else
+ − 216 /* call1 GC-protects its arguments */
853
+ − 217 call1_trapping_problems ("Error in asynchronous timeout callback",
+ − 218 fun, arg, INHIBIT_GC);
593
+ − 219
+ − 220 waiting_for_user_input_p = 0;
771
+ − 221
+ − 222 unbind_to (specco);
593
+ − 223 }
+ − 224
+ − 225 /* The following two functions are the external interface onto
+ − 226 creating/deleting asynchronous interval timeouts, and are
+ − 227 called by event-stream.c. We call back to event-stream.c using
+ − 228 event_stream_resignal_wakeup(), when an interval goes off. */
+ − 229
+ − 230 int
+ − 231 signal_add_async_interval_timeout (EMACS_TIME thyme)
+ − 232 {
+ − 233 int id = add_low_level_timeout (&async_timer_queue, thyme);
+ − 234
+ − 235 /* If this timeout is at the head of the queue, then we need to
+ − 236 set the timer right now for this timeout. Otherwise, things
+ − 237 are fine as-is; after the timers ahead of us are signalled,
+ − 238 the timer will be set for us. */
+ − 239
+ − 240 if (async_timer_queue->id == id)
+ − 241 reset_interval_timer ();
+ − 242
+ − 243 return id;
428
+ − 244 }
+ − 245
+ − 246 void
593
+ − 247 signal_remove_async_interval_timeout (int id)
428
+ − 248 {
593
+ − 249 int first = (async_timer_queue && async_timer_queue->id == id);
+ − 250 remove_low_level_timeout (&async_timer_queue, id);
+ − 251
+ − 252 /* If we removed the timeout from the head of the queue, then
+ − 253 we need to reset the interval timer right now. */
+ − 254 if (first)
+ − 255 reset_interval_timer ();
428
+ − 256 }
+ − 257
593
+ − 258 /* If alarm() gets called when polling isn't disabled, it will mess up
+ − 259 the asynchronous timeouts, and then C-g checking won't work again.
+ − 260 Some libraries call alarm() directly, so we override the standard
+ − 261 library's alarm() and abort() if the caller of the library function
+ − 262 didn't wrap in stop_interrupts()/start_interrupts().
428
+ − 263
593
+ − 264 NOTE: We could potentially avoid the need to wrap by adding a
+ − 265 one-shot timeout to simulate the alarm(), smashing our signal
+ − 266 handler back into place, and calling the library function when the
+ − 267 alarm goes off. But do we want to? We're not going to gain the
+ − 268 ability to C-g out of library functions this way (unless we forcibly
+ − 269 longjmp() out of a signal handler, which is likely to lead to a
+ − 270 crash). --ben */
428
+ − 271
+ − 272 #ifdef HAVE_SETITIMER
611
+ − 273
428
+ − 274 unsigned int
+ − 275 alarm (unsigned int howlong)
+ − 276 {
+ − 277 struct itimerval old_it, new_it;
+ − 278
+ − 279 assert (async_timer_suppress_count > 0);
+ − 280
+ − 281 new_it.it_value.tv_sec = howlong;
+ − 282 new_it.it_value.tv_usec = 0;
+ − 283 new_it.it_interval.tv_sec = 0;
+ − 284 new_it.it_interval.tv_usec = 0;
611
+ − 285 qxe_setitimer (ITIMER_REAL, &new_it, &old_it);
428
+ − 286
+ − 287 /* Never return zero if there was a timer outstanding. */
+ − 288 return old_it.it_value.tv_sec + (old_it.it_value.tv_usec > 0 ? 1 : 0);
+ − 289 }
611
+ − 290
+ − 291 int
+ − 292 qxe_setitimer (int kind, const struct itimerval *itnew,
+ − 293 struct itimerval *itold)
+ − 294 {
+ − 295 #if defined (WIN32_NATIVE) || defined (CYGWIN)
+ − 296 /* setitimer() does not exist on native MS Windows, and appears broken
617
+ − 297 on Cygwin. See win32.c.
+ − 298
+ − 299 We are emulating the Unix98 setitimer() function, as found in its
+ − 300 incarnations on modern versions of Unix. Note however that in
+ − 301 the win32.c version, ITNEW and ITOLD must be equal if both are
+ − 302 non-zero, due to limitations in the underlying multimedia-timer
+ − 303 API. */
611
+ − 304 return mswindows_setitimer (kind, itnew, itold);
+ − 305 #else
617
+ − 306 /* YUCK! glibc defines setitimer's first argument as
+ − 307 enum __itimer_which, not int, which causes compile errors if
+ − 308 we call setitimer() in the obvious way. */
+ − 309 switch (kind)
+ − 310 {
+ − 311 case ITIMER_REAL: return setitimer (ITIMER_REAL, itnew, itold);
+ − 312 case ITIMER_VIRTUAL: return setitimer (ITIMER_VIRTUAL, itnew, itold);
+ − 313 case ITIMER_PROF: return setitimer (ITIMER_PROF, itnew, itold);
+ − 314 default: abort (); return 0;
+ − 315 }
428
+ − 316 #endif
611
+ − 317 }
+ − 318
+ − 319 #endif /* HAVE_SETITIMER */
+ − 320
613
+ − 321 signal_handler_t
+ − 322 set_timeout_signal (int signal_number, signal_handler_t action)
+ − 323 {
+ − 324 #ifdef CYGWIN_BROKEN_SIGNALS
+ − 325 return mswindows_sigset (signal_number, action);
+ − 326 #else
+ − 327 return EMACS_SIGNAL (signal_number, action);
+ − 328 #endif
+ − 329 }
428
+ − 330
+ − 331 DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, 0, 0, 0, /*
+ − 332 Return non-nil if XEmacs is waiting for input from the user.
+ − 333 This is intended for use by asynchronous timeout callbacks and by
+ − 334 asynchronous process output filters and sentinels (not yet implemented
+ − 335 in XEmacs). It will always be nil if XEmacs is not inside of
+ − 336 an asynchronous timeout or process callback.
+ − 337 */
+ − 338 ())
+ − 339 {
+ − 340 return waiting_for_user_input_p ? Qt : Qnil;
+ − 341 }
+ − 342
+ − 343
+ − 344 /**********************************************************************/
593
+ − 345 /* Enabling/disabling signals */
+ − 346 /**********************************************************************/
+ − 347
+ − 348 static int interrupts_initted;
+ − 349
+ − 350 void
+ − 351 stop_interrupts (void)
+ − 352 {
+ − 353 if (!interrupts_initted)
+ − 354 return;
+ − 355 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
+ − 356 unrequest_sigio ();
+ − 357 #endif
+ − 358 stop_async_timeouts ();
+ − 359 }
+ − 360
+ − 361 void
+ − 362 start_interrupts (void)
+ − 363 {
+ − 364 if (!interrupts_initted)
+ − 365 return;
+ − 366 #if defined(SIGIO) && !defined(BROKEN_SIGIO)
+ − 367 request_sigio ();
+ − 368 #endif
+ − 369 start_async_timeouts ();
+ − 370 }
+ − 371
+ − 372
+ − 373 static void
+ − 374 establish_slow_interrupt_timer (void)
+ − 375 {
+ − 376 EMACS_TIME thyme;
+ − 377
+ − 378 EMACS_SET_SECS_USECS (thyme, SLOWED_DOWN_INTERRUPTS_SECS, 0);
+ − 379 set_one_shot_timer (thyme);
+ − 380 }
+ − 381
+ − 382 /* Some functions don't like being interrupted with SIGALRM or SIGIO.
+ − 383 Previously we were calling stop_interrupts() / start_interrupts(),
+ − 384 but then if the program hangs in one of those functions, e.g.
+ − 385 waiting for a connect(), we're really screwed. So instead we
+ − 386 just "slow them down". We do this by disabling all interrupts
+ − 387 and then installing a timer of length fairly large, like 5 or
+ − 388 10 secs. That way, any "legitimate" connections (which should
+ − 389 take a fairly short amount of time) go through OK, but we can
+ − 390 interrupt bogus ones. */
+ − 391
+ − 392 void
+ − 393 slow_down_interrupts (void)
+ − 394 {
+ − 395 /* We have to set the flag *before* setting the slowed-down timer,
+ − 396 to avoid a race condition -- if the signal occurs between the
+ − 397 call to set_one_shot_timer() and the setting of this flag,
+ − 398 async_timeout_happened will get set, which will be a Bad Thing if
+ − 399 there were no timeouts on the queue. */
+ − 400 interrupts_slowed_down++;
+ − 401 if (interrupts_slowed_down == 1)
+ − 402 {
+ − 403 stop_interrupts ();
+ − 404 establish_slow_interrupt_timer ();
+ − 405 }
+ − 406 }
+ − 407
+ − 408 void
+ − 409 speed_up_interrupts (void)
+ − 410 {
+ − 411 if (interrupts_slowed_down > 0)
+ − 412 {
+ − 413 start_interrupts ();
+ − 414 /* Change this flag AFTER fiddling with interrupts, for the same
+ − 415 race-condition reasons as above. */
+ − 416 interrupts_slowed_down--;
+ − 417 }
+ − 418 }
+ − 419
+ − 420
+ − 421 /**********************************************************************/
+ − 422 /* The mechanism that drives it all */
428
+ − 423 /**********************************************************************/
+ − 424
593
+ − 425 /* called from QUIT when something_happened gets set (as a result of
+ − 426 a signal) */
+ − 427
853
+ − 428 void
593
+ − 429 check_what_happened (void)
+ − 430 {
853
+ − 431 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS
+ − 432 if (in_display
+ − 433 && !((get_inhibit_flags () & INTERNAL_INHIBIT_ERRORS)
+ − 434 && (get_inhibit_flags () & INTERNAL_INHIBIT_THROWS)))
+ − 435 assert_with_message
+ − 436 (0, "QUIT called from within redisplay without being properly wrapped");
+ − 437 #endif
+ − 438
771
+ − 439 /* No GC can happen anywhere here. handle_async_timeout_signal()
+ − 440 prevents GC (from asynch timeout handler), so does check_quit()
+ − 441 (from processing a message such as WM_INITMENU as a result of
+ − 442 draining the message queue). establish_slow_interrupt_timer() is
+ − 443 too low-level to do anything that might invoke QUIT or call Lisp
+ − 444 code. */
593
+ − 445 something_happened = 0;
+ − 446 if (async_timeout_happened)
+ − 447 {
+ − 448 async_timeout_happened = 0;
+ − 449 handle_async_timeout_signal ();
+ − 450 }
+ − 451 if (slowed_interrupt_timeout_happened)
+ − 452 {
+ − 453 slowed_interrupt_timeout_happened = 0;
+ − 454 establish_slow_interrupt_timer ();
+ − 455 }
+ − 456
853
+ − 457 check_quit ();
593
+ − 458 }
+ − 459
+ − 460 #ifdef SIGIO
+ − 461
+ − 462 /* Signal handler for SIGIO. */
+ − 463
+ − 464 static void
+ − 465 input_available_signal (int signo)
+ − 466 {
+ − 467 something_happened = 1; /* tell QUIT to wake up */
+ − 468 quit_check_signal_happened = 1;
+ − 469 quit_check_signal_tick_count++;
+ − 470 EMACS_REESTABLISH_SIGNAL (signo, input_available_signal);
+ − 471 SIGRETURN;
+ − 472 }
+ − 473
+ − 474 #endif /* SIGIO */
+ − 475
+ − 476 /* Actual signal handler for SIGALRM. Called when:
+ − 477
+ − 478 -- asynchronous timeouts (added with `add-async-timeout') go off
+ − 479
+ − 480 -- when the poll-for-quit timer (used for C-g handling; more or
+ − 481 less when SIGIO is unavailable or BROKEN_SIGIO is defined) or
+ − 482 poll-for-sigchld timer (used when BROKEN_SIGCHLD is defined) go
+ − 483 off. The latter two timers, if set, normally go off every 1/4
+ − 484 of a second -- see NORMAL_QUIT_CHECK_TIMEOUT_MSECS and
+ − 485 NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS. (Both of these timers are
+ − 486 treated like other asynchronous timeouts, but special-cased
+ − 487 in handle_async_timeout_signal().)
+ − 488
+ − 489 -- we called slow_down_interrupts() and SLOWED_DOWN_INTERRUPTS_SECS
+ − 490 (or a multiple of it) has elapsed.
+ − 491
+ − 492 Note that under Windows, we have no working setitimer(), so we
+ − 493 simulate it using the multimedia timeout functions,
+ − 494 e.g. timeSetEvent(). See setitimer() in nt.c.
+ − 495
+ − 496 Note also that we don't actually *do* anything here (except in the
+ − 497 case of can_break_system_calls). Instead, we just set various
+ − 498 flags; next time QUIT is called, the flags will cause
+ − 499 check_what_happened() to be called, at which point we do everything
+ − 500 indicated by the flags.
+ − 501 */
+ − 502
+ − 503 static SIGTYPE
+ − 504 alarm_signal (int signo)
+ − 505 {
+ − 506 something_happened = 1; /* tell QUIT to wake up and call
+ − 507 check_what_happened() */
+ − 508
+ − 509 if (interrupts_slowed_down)
+ − 510 {
+ − 511 /* we are in "slowed-down interrupts" mode; the only alarm
+ − 512 happening here is the slowed-down quit-check alarm, so
+ − 513 we set this flag.
+ − 514
+ − 515 Do NOT set async_timeout_happened, because we don't want
+ − 516 anyone looking at the timeout queue -- async timeouts
+ − 517 are disabled. */
+ − 518 quit_check_signal_happened = 1;
+ − 519 quit_check_signal_tick_count++;
+ − 520 /* make sure we establish the slow timer again. */
+ − 521 slowed_interrupt_timeout_happened = 1;
+ − 522
+ − 523 /* can_break_system_calls is set when we want to break out of
+ − 524 non-interruptible system calls. */
+ − 525 if (can_break_system_calls)
+ − 526 {
+ − 527 /* reset the flag for safety and such. Do this *before*
+ − 528 unblocking or reestablishing the signal to avoid potential
+ − 529 race conditions. */
+ − 530 can_break_system_calls = 0;
+ − 531 #ifndef WIN32_NATIVE
+ − 532 /* #### I didn't add this WIN32_NATIVE check. I'm not sure
+ − 533 why it's here. But then again, someone needs to review
+ − 534 this can_break_system_calls stuff and see if it still
+ − 535 makes sense. --ben */
+ − 536 EMACS_UNBLOCK_SIGNAL (signo);
+ − 537 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal);
+ − 538 LONGJMP (break_system_call_jump, 0);
+ − 539 #endif
+ − 540 }
+ − 541 }
+ − 542 else
+ − 543 {
+ − 544 async_timeout_happened = 1;
+ − 545 if (emacs_is_blocking)
+ − 546 async_timeout_happened_while_emacs_was_blocking = 1;
+ − 547 /* #### This is for QUITP. When it is run, it may not be the
+ − 548 place to do arbitrary stuff like run asynch. handlers, but
+ − 549 it needs to know whether the poll-for-quit asynch. timeout
+ − 550 went off. Rather than put the code in to compute this
+ − 551 specially, we just set this flag. Should fix this. */
+ − 552 quit_check_signal_happened = 1;
+ − 553
+ − 554 #ifdef HAVE_UNIXOID_EVENT_LOOP
+ − 555 signal_fake_event ();
+ − 556 #endif
+ − 557 }
+ − 558
+ − 559 EMACS_REESTABLISH_SIGNAL (signo, alarm_signal);
+ − 560 SIGRETURN;
+ − 561 }
+ − 562
428
+ − 563 /* Set this for debugging, to have a way to get out */
+ − 564 int stop_character; /* #### not currently implemented */
+ − 565
593
+ − 566 /* Signal handler for SIGINT and SIGQUIT. On TTY's, one of these two
+ − 567 signals will get generated in response to C-g. (When running under
+ − 568 X, C-g is handled using the SIGIO handler, which sets a flag
+ − 569 telling the QUIT macro to scan the unread events for a ^G.)
+ − 570 */
428
+ − 571
+ − 572 static SIGTYPE
+ − 573 interrupt_signal (int sig)
+ − 574 {
+ − 575 /* This function can call lisp */
+ − 576 /* #### we should NOT be calling lisp from a signal handler, boys
+ − 577 and girls */
+ − 578 /* Must preserve main program's value of errno. */
+ − 579 int old_errno = errno;
+ − 580
+ − 581 EMACS_REESTABLISH_SIGNAL (sig, interrupt_signal);
+ − 582
+ − 583 if (sigint_happened && CONSOLEP (Vcontrolling_terminal) &&
+ − 584 CONSOLE_LIVE_P (XCONSOLE (Vcontrolling_terminal)) &&
+ − 585 !emacs_is_blocking)
+ − 586 {
593
+ − 587 /* #### this is inherited from GNU Emacs. Do we really want this?
+ − 588 --ben */
428
+ − 589 char c;
+ − 590 fflush (stdout);
+ − 591 reset_initial_console ();
+ − 592 EMACS_UNBLOCK_SIGNAL (sig);
+ − 593 #ifdef SIGTSTP /* Support possible in later USG versions */
+ − 594 /*
+ − 595 * On systems which can suspend the current process and return to the original
+ − 596 * shell, this command causes the user to end up back at the shell.
+ − 597 * The "Auto-save" and "Abort" questions are not asked until
+ − 598 * the user elects to return to emacs, at which point he can save the current
+ − 599 * job and either dump core or continue.
+ − 600 */
+ − 601 sys_suspend ();
+ − 602 #else
+ − 603 /* Perhaps should really fork an inferior shell?
+ − 604 But that would not provide any way to get back
+ − 605 to the original shell, ever. */
+ − 606 stdout_out ("No support for stopping a process on this operating system;\n");
+ − 607 stdout_out ("you can continue or abort.\n");
+ − 608 #endif /* not SIGTSTP */
+ − 609 stdout_out ("Auto-save? (y or n) ");
+ − 610 if (((c = getc (stdin)) & ~040) == 'Y')
+ − 611 Fdo_auto_save (Qnil, Qnil);
+ − 612 while (c != '\n')
+ − 613 c = getc (stdin);
+ − 614 stdout_out ("Abort (and dump core)? (y or n) ");
+ − 615 if (((c = getc (stdin)) & ~040) == 'Y')
+ − 616 abort ();
+ − 617 while (c != '\n')
+ − 618 c = getc (stdin);
+ − 619 stdout_out ("Continuing...\n");
+ − 620 reinit_initial_console ();
+ − 621 MARK_FRAME_CHANGED (XFRAME (DEVICE_SELECTED_FRAME
+ − 622 (XDEVICE (CONSOLE_SELECTED_DEVICE
+ − 623 (XCONSOLE
+ − 624 (Vcontrolling_terminal))))));
+ − 625 }
+ − 626 else
+ − 627 {
+ − 628 /* Else request quit when it's safe */
+ − 629 Vquit_flag = Qt;
+ − 630 sigint_happened = 1;
+ − 631 #ifdef HAVE_UNIXOID_EVENT_LOOP
+ − 632 signal_fake_event ();
+ − 633 #endif
+ − 634 }
+ − 635 errno = old_errno;
+ − 636 SIGRETURN;
+ − 637 }
+ − 638
593
+ − 639
+ − 640 /**********************************************************************/
+ − 641 /* Control-G checking */
+ − 642 /**********************************************************************/
+ − 643
853
+ − 644 /* Note: The code to handle QUIT is divided between lisp.h and signal.c.
+ − 645 There is also some special-case code in the async timer code in
+ − 646 event-stream.c to notice when the poll-for-quit (and poll-for-sigchld)
+ − 647 timers have gone off. */
+ − 648
+ − 649 /* OK, here's an overview of how this convoluted stuff works:
+ − 650
+ − 651 [1] Scattered throughout the XEmacs core code are calls to the macro QUIT;
+ − 652 This macro checks to see whether a C-g has recently been pressed and
+ − 653 not yet handled, and if so, it handles the C-g by calling signal_quit(),
+ − 654 which invokes the standard Fsignal() code, with the error being Qquit.
+ − 655 Lisp code can establish handlers for this (using condition-case), but
+ − 656 normally there is no handler, and so execution is thrown back to the
+ − 657 innermost enclosing event loop. (One of the things that happens when
+ − 658 entering an event loop is that a condition-case is established that
+ − 659 catches *all* calls to `signal', including this one.)
+ − 660
+ − 661 [2] How does the QUIT macro check to see whether C-g has been pressed;
+ − 662 obviously this needs to be extremely fast. Now for some history.
+ − 663 In early Lemacs as inherited from the FSF going back 15 years or
+ − 664 more, there was a great fondness for using SIGIO (which is sent
+ − 665 whenever there is I/O available on a given socket, tty, etc.).
+ − 666 In fact, in GNU Emacs, perhaps even today, all reading of events
+ − 667 from the X server occurs inside the SIGIO handler! This is crazy,
+ − 668 but not completely relevant. What is relevant is that similar
+ − 669 stuff happened inside the SIGIO handler for C-g: it searched
+ − 670 through all the pending (i.e. not yet delivered to XEmacs yet)
+ − 671 X events for one that matched C-g. When it saw a match, it set
+ − 672 Vquit_flag to Qt. On TTY's, C-g is actually mapped to be the
+ − 673 interrupt character (i.e. it generates SIGINT), and XEmacs's
+ − 674 handler for this signal sets Vquit_flag to Qt. Then, sometime
+ − 675 later after the signal handlers finished and a QUIT macro was
+ − 676 called, the macro noticed the setting of Vquit_flag and used
+ − 677 this as an indication to call signal_quit(). What signal_quit()
+ − 678 actually does is set Vquit_flag to Qnil (so that we won't get
+ − 679 repeated interruptions from a single C-g press) and then calls
+ − 680 the equivalent of (signal 'quit nil).
+ − 681
+ − 682 [3] Another complication is introduced in that Vquit_flag is actually
+ − 683 exported to Lisp as `quit-flag'. This allows users some level of
+ − 684 control over whether and when C-g is processed as quit, esp. in
+ − 685 combination with `inhibit-quit'. This is another Lisp variable,
+ − 686 and if set to non-nil, it inhibits signal_quit() from getting
+ − 687 called, meaning that the C-g gets essentially ignored. But not
+ − 688 completely: Because the resetting of `quit-flag' happens only
+ − 689 in signal_quit(), which isn't getting called, the C-g press is
+ − 690 still noticed, and as soon as `inhibit-quit' is set back to nil,
+ − 691 a quit will be signalled at the next QUIT macro. Thus, what
+ − 692 `inhibit-quit' really does is defer quits until after the quit-
+ − 693 inhibitted period.
+ − 694
+ − 695 [4] Another consideration, introduced by XEmacs, is critical quitting.
+ − 696 If you press Control-Shift-G instead of just C-g, `quit-flag' is
+ − 697 set to `critical' instead of to t. When QUIT processes this value,
+ − 698 it *ignores* the value of `inhibit-quit'. This allows you to quit
+ − 699 even out of a quit-inhibitted section of code! Furthermore, when
+ − 700 signal_quit() notices that it was invoked as a result of a critical
+ − 701 quit, it automatically invokes the debugger (which otherwise would
+ − 702 only happen when `debug-on-quit' is set to t).
+ − 703
+ − 704 [5] Well, I explained above about how `quit-flag' gets set correctly,
+ − 705 but I began with a disclaimer stating that this was the old way
+ − 706 of doing things. What's done now? Well, first of all, the SIGIO
+ − 707 handler (which formerly checked all pending events to see if there's
+ − 708 a C-g) now does nothing but set a flag -- or actually two flags,
+ − 709 something_happened and quit_check_signal_happened. There are two
+ − 710 flags because the QUIT macro is now used for more than just handling
+ − 711 QUIT; it's also used for running asynchronous timeout handlers that
+ − 712 have recently expired, and perhaps other things. The idea here is
+ − 713 that the QUIT macros occur extremely often in the code, but only occur
+ − 714 at places that are relatively safe -- in particular, if an error occurs,
+ − 715 nothing will get completely trashed.
+ − 716
+ − 717 [6] Now, let's look at QUIT again.
+ − 718
+ − 719 UNFINISHED. Note, however, that as of the point when this comment
+ − 720 got committed to CVS (mid-2001), the interaction between reading
+ − 721 C-g as an event and processing it as QUIT was overhauled to (for
+ − 722 the first time) be understandable and actually work correctly.
+ − 723 Now, the way things work is that if C-g is pressed while XEmacs is
+ − 724 blocking at the top level, waiting for a user event, it will be
+ − 725 read as an event; otherwise, it will cause QUIT. (This includes
+ − 726 times when XEmacs is blocking, but not waiting for a user event,
+ − 727 e.g. accept-process-output and wait_delaying_user_events().)
+ − 728 Formerly, this was supposed to happen, but didn't always due to a
+ − 729 bizarre and broken scheme, documented in next_event_internal
+ − 730 like this:
+ − 731
+ − 732 If we read a ^G, then set quit-flag but do not discard the ^G.
+ − 733 The callers of next_event_internal() will do one of two things:
+ − 734
+ − 735 -- set Vquit_flag to Qnil. (next-event does this.) This will
+ − 736 cause the ^G to be treated as a normal keystroke.
+ − 737 -- not change Vquit_flag but attempt to enqueue the ^G, at
+ − 738 which point it will be discarded. The next time QUIT is
+ − 739 called, it will notice that Vquit_flag was set.
+ − 740
+ − 741 This required weirdness in enqueue_command_event_1 like this:
+ − 742
+ − 743 put the event on the typeahead queue, unless
+ − 744 the event is the quit char, in which case the `QUIT'
+ − 745 which will occur on the next trip through this loop is
+ − 746 all the processing we should do - leaving it on the queue
+ − 747 would cause the quit to be processed twice.
+ − 748
+ − 749 And further weirdness elsewhere, none of which made any sense,
+ − 750 and didn't work, because (e.g.) it required that QUIT never
+ − 751 happen anywhere inside next_event_internal() or any callers when
+ − 752 C-g should be read as a user event, which was impossible to
+ − 753 implement in practice.
+ − 754
+ − 755 Now what we do is fairly simple. Callers of next_event_internal()
+ − 756 that want C-g read as a user event call begin_dont_check_for_quit().
+ − 757 next_event_internal(), when it gets a C-g, simply sets Vquit_flag
+ − 758 (just as when a C-g is detected during the operation of QUIT or
+ − 759 QUITP), and then tries to QUIT. This will fail if blocked by the
+ − 760 previous call, at which point next_event_internal() will return
+ − 761 the C-g as an event. To unblock things, first set Vquit_flag to
+ − 762 nil (it was set to t when the C-g was read, and if we don't reset
+ − 763 it, the next call to QUIT will quit), and then unbind_to() the
+ − 764 depth returned by begin_dont_check_for_quit(). It makes no
+ − 765 difference is QUIT is called a zillion times in next_event_internal()
+ − 766 or anywhere else, because it's blocked and will never signal.
+ − 767
+ − 768 --ben
+ − 769 */
+ − 770
+ − 771
771
+ − 772 /* Defer all checking or processing of C-g. You can do this, for example,
+ − 773 if you want to read C-g's as events. (In that case, you should set
+ − 774 Vquit_flag to Qnil just before you unbind, because it typically gets set
+ − 775 as a result of reading C-g.) */
+ − 776
+ − 777 int
428
+ − 778 begin_dont_check_for_quit (void)
+ − 779 {
771
+ − 780 int depth = specpdl_depth ();
+ − 781 /* As an optimization in QUIT_FLAG_SAYS_SHOULD_QUIT, we bind inhibit-quit
+ − 782 to t -- it has to be checked anyway, and by doing this, we only need
+ − 783 to check dont_check_for_quit when quit-flag == `critical', which is
+ − 784 rare. */
428
+ − 785 specbind (Qinhibit_quit, Qt);
853
+ − 786 internal_bind_int (&dont_check_for_quit, 1);
771
+ − 787
+ − 788 return depth;
428
+ − 789 }
+ − 790
853
+ − 791 /* If we're inside of a begin_dont_check_for_quit() section, but want
+ − 792 to temporarily enable quit-checking, call this. This is used in
+ − 793 particular when processing menu filters -- some menu filters do
+ − 794 antisocial things like load large amounts of Lisp code (custom in
+ − 795 particular), and we obviously want a way of breaking out of any
+ − 796 problems. If you do use this, you should really be trapping the
+ − 797 throw() that comes from the quitting (as does the code that handles
+ − 798 menus popping up). */
+ − 799
428
+ − 800 int
853
+ − 801 begin_do_check_for_quit (void)
+ − 802 {
+ − 803 int depth = specpdl_depth ();
+ − 804 specbind (Qinhibit_quit, Qnil);
+ − 805 internal_bind_int (&dont_check_for_quit, 0);
+ − 806 /* #### should we set Vquit_flag to Qnil? */
+ − 807 return depth;
+ − 808 }
+ − 809
+ − 810 /* The effect of this function is to set Vquit_flag appropriately if the
+ − 811 user pressed C-g or Sh-C-g. After this function finishes, Vquit_flag
+ − 812 will be Qt for C-g, Qcritical for Sh-C-g, and unchanged otherwise.
+ − 813 The C-g or Sh-C-g is discarded, so it won't be noticed again.
+ − 814 */
+ − 815
+ − 816 void
428
+ − 817 check_quit (void)
+ − 818 {
853
+ − 819 /* dont_check_for_quit is set in three circumstances:
428
+ − 820
+ − 821 (1) when we are in the process of changing the window
+ − 822 configuration. The frame might be in an inconsistent state,
+ − 823 which will cause assertion failures if we check for QUIT.
+ − 824
+ − 825 (2) when we are reading events, and want to read the C-g
+ − 826 as an event. The normal check for quit will discard the C-g,
+ − 827 which would be bad.
+ − 828
853
+ − 829 (3) when we're going down with a fatal error. we're most likely
+ − 830 in an inconsistent state, and we definitely don't want to be
+ − 831 interrupted. */
428
+ − 832
853
+ − 833 /* We should *not* conditionalize on Vinhibit_quit, or
428
+ − 834 critical-quit (Control-Shift-G) won't work right. */
+ − 835
771
+ − 836 /* WARNING: Even calling check_quit(), without actually dispatching
+ − 837 a quit signal, can result in arbitrary Lisp code getting executed
+ − 838 -- at least under Windows. (Not to mention obvious Lisp
+ − 839 invocations like asynchronous timer callbacks.) Here's a sample
+ − 840 stack trace to demonstrate:
+ − 841
+ − 842 NTDLL! DbgBreakPoint@0 address 0x77f9eea9
+ − 843 assert_failed(const char * 0x012d036c, int 4596, const char * 0x012d0354) line 3478
+ − 844 re_match_2_internal(re_pattern_buffer * 0x012d6780, const unsigned char * 0x00000000, int 0, const unsigned char * 0x022f9328, int 34, int 0, re_registers * 0x012d53d0 search_regs, int 34) line 4596 + 41 bytes
+ − 845 re_search_2(re_pattern_buffer * 0x012d6780, const char * 0x00000000, int 0, const char * 0x022f9328, int 34, int 0, int 34, re_registers * 0x012d53d0 search_regs, int 34) line 4269 + 37 bytes
+ − 846 re_search(re_pattern_buffer * 0x012d6780, const char * 0x022f9328, int 34, int 0, int 34, re_registers * 0x012d53d0 search_regs) line 4031 + 37 bytes
+ − 847 string_match_1(long 31222628, long 30282164, long 28377092, buffer * 0x022fde00, int 0) line 413 + 69 bytes
+ − 848 Fstring_match(long 31222628, long 30282164, long 28377092, long 28377092) line 436 + 34 bytes
+ − 849 Ffuncall(int 3, long * 0x008297f8) line 3488 + 168 bytes
+ − 850 execute_optimized_program(const unsigned char * 0x020ddc50, int 6, long * 0x020ddf50) line 744 + 16 bytes
+ − 851 funcall_compiled_function(long 34407748, int 1, long * 0x00829aec) line 516 + 53 bytes
+ − 852 Ffuncall(int 2, long * 0x00829ae8) line 3523 + 17 bytes
+ − 853 execute_optimized_program(const unsigned char * 0x020ddc90, int 4, long * 0x020ddf90) line 744 + 16 bytes
+ − 854 funcall_compiled_function(long 34407720, int 1, long * 0x00829e28) line 516 + 53 bytes
+ − 855 Ffuncall(int 2, long * 0x00829e24) line 3523 + 17 bytes
+ − 856 mapcar1(long 15, long * 0x00829e48, long 34447820, long 34187868) line 2929 + 11 bytes
+ − 857 Fmapcar(long 34447820, long 34187868) line 3035 + 21 bytes
+ − 858 Ffuncall(int 3, long * 0x00829f20) line 3488 + 93 bytes
+ − 859 execute_optimized_program(const unsigned char * 0x020c2b70, int 7, long * 0x020dd010) line 744 + 16 bytes
+ − 860 funcall_compiled_function(long 34407580, int 2, long * 0x0082a210) line 516 + 53 bytes
+ − 861 Ffuncall(int 3, long * 0x0082a20c) line 3523 + 17 bytes
+ − 862 execute_optimized_program(const unsigned char * 0x020cf810, int 6, long * 0x020cfb10) line 744 + 16 bytes
+ − 863 funcall_compiled_function(long 34407524, int 0, long * 0x0082a580) line 516 + 53 bytes
+ − 864 Ffuncall(int 1, long * 0x0082a57c) line 3523 + 17 bytes
+ − 865 run_hook_with_args_in_buffer(buffer * 0x022fde00, int 1, long * 0x0082a57c, int 0) line 3980 + 13 bytes
+ − 866 run_hook_with_args(int 1, long * 0x0082a57c, int 0) line 3993 + 23 bytes
+ − 867 Frun_hooks(int 1, long * 0x0082a57c) line 3847 + 19 bytes
+ − 868 run_hook(long 34447484) line 4094 + 11 bytes
+ − 869 unsafe_handle_wm_initmenu_1(frame * 0x01dbb000) line 736 + 11 bytes
+ − 870 unsafe_handle_wm_initmenu(long 28377092) line 807 + 11 bytes
+ − 871 condition_case_1(long 28377116, long (long)* 0x0101c827 unsafe_handle_wm_initmenu(long), long 28377092, long (long, long)* 0x01005fa4 mswindows_modal_loop_error_handler(long, long), long 28377092) line 1692 + 7 bytes
+ − 872 mswindows_protect_modal_loop(long (long)* 0x0101c827 unsafe_handle_wm_initmenu(long), long 28377092) line 1194 + 32 bytes
+ − 873 mswindows_handle_wm_initmenu(HMENU__ * 0x00010199, frame * 0x01dbb000) line 826 + 17 bytes
+ − 874 mswindows_wnd_proc(HWND__ * 0x000501da, unsigned int 278, unsigned int 65945, long 0) line 3089 + 31 bytes
+ − 875 USER32! UserCallWinProc@20 + 24 bytes
+ − 876 USER32! DispatchClientMessage@20 + 47 bytes
+ − 877 USER32! __fnDWORD@4 + 34 bytes
+ − 878 NTDLL! KiUserCallbackDispatcher@12 + 19 bytes
+ − 879 USER32! DispatchClientMessage@20 address 0x77e163cc
+ − 880 USER32! DefWindowProcW@16 + 34 bytes
+ − 881 qxeDefWindowProc(HWND__ * 0x000501da, unsigned int 274, unsigned int 61696, long 98) line 1188 + 22 bytes
+ − 882 mswindows_wnd_proc(HWND__ * 0x000501da, unsigned int 274, unsigned int 61696, long 98) line 3362 + 21 bytes
+ − 883 USER32! UserCallWinProc@20 + 24 bytes
+ − 884 USER32! DispatchClientMessage@20 + 47 bytes
+ − 885 USER32! __fnDWORD@4 + 34 bytes
+ − 886 NTDLL! KiUserCallbackDispatcher@12 + 19 bytes
+ − 887 USER32! DispatchClientMessage@20 address 0x77e163cc
+ − 888 USER32! DefWindowProcW@16 + 34 bytes
+ − 889 qxeDefWindowProc(HWND__ * 0x000501da, unsigned int 262, unsigned int 98, long 540016641) line 1188 + 22 bytes
+ − 890 mswindows_wnd_proc(HWND__ * 0x000501da, unsigned int 262, unsigned int 98, long 540016641) line 3362 + 21 bytes
+ − 891 USER32! UserCallWinProc@20 + 24 bytes
+ − 892 USER32! DispatchMessageWorker@8 + 244 bytes
+ − 893 USER32! DispatchMessageW@4 + 11 bytes
+ − 894 qxeDispatchMessage(const tagMSG * 0x0082c684 {msg=0x00000106 wp=0x00000062 lp=0x20300001}) line 989 + 10 bytes
+ − 895 mswindows_drain_windows_queue() line 1345 + 9 bytes
+ − 896 emacs_mswindows_quit_p() line 3947
+ − 897 event_stream_quit_p() line 666
+ − 898 check_quit() line 686
+ − 899 check_what_happened() line 437
+ − 900 re_match_2_internal(re_pattern_buffer * 0x012d5a18, const unsigned char * 0x00000000, int 0, const unsigned char * 0x02235000, int 23486, int 14645, re_registers * 0x012d53d0 search_regs, int 23486) line 4717 + 14 bytes
+ − 901 re_search_2(re_pattern_buffer * 0x012d5a18, const char * 0x02235000, int 23486, const char * 0x0223b38e, int 0, int 14645, int 8841, re_registers * 0x012d53d0 search_regs, int 23486) line 4269 + 37 bytes
+ − 902 search_buffer(buffer * 0x022fde00, long 29077572, long 13789, long 23487, long 1, int 1, long 28377092, long 28377092, int 0) line 1224 + 89 bytes
+ − 903 search_command(long 29077572, long 46975, long 28377116, long 28377092, long 28377092, int 1, int 1, int 0) line 1054 + 151 bytes
+ − 904 Fre_search_forward(long 29077572, long 46975, long 28377116, long 28377092, long 28377092) line 2147 + 31 bytes
+ − 905 Ffuncall(int 4, long * 0x0082ceb0) line 3488 + 216 bytes
+ − 906 execute_optimized_program(const unsigned char * 0x02047810, int 13, long * 0x02080c10) line 744 + 16 bytes
+ − 907 funcall_compiled_function(long 34187208, int 3, long * 0x0082d1b8) line 516 + 53 bytes
+ − 908 Ffuncall(int 4, long * 0x0082d1b4) line 3523 + 17 bytes
+ − 909 execute_optimized_program(const unsigned char * 0x01e96a10, int 6, long * 0x020ae510) line 744 + 16 bytes
+ − 910 funcall_compiled_function(long 34186676, int 3, long * 0x0082d4a0) line 516 + 53 bytes
+ − 911 Ffuncall(int 4, long * 0x0082d49c) line 3523 + 17 bytes
+ − 912 execute_optimized_program(const unsigned char * 0x02156b50, int 4, long * 0x020c2db0) line 744 + 16 bytes
+ − 913 funcall_compiled_function(long 34186564, int 2, long * 0x0082d780) line 516 + 53 bytes
+ − 914 Ffuncall(int 3, long * 0x0082d77c) line 3523 + 17 bytes
+ − 915 execute_optimized_program(const unsigned char * 0x0082d964, int 3, long * 0x020c2d70) line 744 + 16 bytes
+ − 916 Fbyte_code(long 29405156, long 34352480, long 7) line 2392 + 38 bytes
+ − 917 Feval(long 34354440) line 3290 + 187 bytes
+ − 918 condition_case_1(long 34354572, long (long)* 0x01087232 Feval(long), long 34354440, long (long, long)* 0x01084764 run_condition_case_handlers(long, long), long 28377092) line 1692 + 7 bytes
+ − 919 condition_case_3(long 34354440, long 28377092, long 34354572) line 1779 + 27 bytes
+ − 920 execute_rare_opcode(long * 0x0082dc7c, const unsigned char * 0x01b090af, int 143) line 1269 + 19 bytes
+ − 921 execute_optimized_program(const unsigned char * 0x01b09090, int 6, long * 0x020ae590) line 654 + 17 bytes
+ − 922 funcall_compiled_function(long 34186620, int 0, long * 0x0082df68) line 516 + 53 bytes
+ − 923 Ffuncall(int 1, long * 0x0082df64) line 3523 + 17 bytes
+ − 924 execute_optimized_program(const unsigned char * 0x02195470, int 1, long * 0x020c2df0) line 744 + 16 bytes
+ − 925 funcall_compiled_function(long 34186508, int 0, long * 0x0082e23c) line 516 + 53 bytes
+ − 926 Ffuncall(int 1, long * 0x0082e238) line 3523 + 17 bytes
+ − 927 execute_optimized_program(const unsigned char * 0x01e5d410, int 6, long * 0x0207d410) line 744 + 16 bytes
+ − 928 funcall_compiled_function(long 34186312, int 1, long * 0x0082e524) line 516 + 53 bytes
+ − 929 Ffuncall(int 2, long * 0x0082e520) line 3523 + 17 bytes
+ − 930 execute_optimized_program(const unsigned char * 0x02108fb0, int 2, long * 0x020c2e30) line 744 + 16 bytes
+ − 931 funcall_compiled_function(long 34186340, int 0, long * 0x0082e7fc) line 516 + 53 bytes
+ − 932 Ffuncall(int 1, long * 0x0082e7f8) line 3523 + 17 bytes
+ − 933 execute_optimized_program(const unsigned char * 0x020fe150, int 2, long * 0x01e6f510) line 744 + 16 bytes
+ − 934 funcall_compiled_function(long 31008124, int 0, long * 0x0082ebd8) line 516 + 53 bytes
+ − 935 Ffuncall(int 1, long * 0x0082ebd4) line 3523 + 17 bytes
+ − 936 run_hook_with_args_in_buffer(buffer * 0x022fde00, int 1, long * 0x0082ebd4, int 0) line 3980 + 13 bytes
+ − 937 run_hook_with_args(int 1, long * 0x0082ebd4, int 0) line 3993 + 23 bytes
+ − 938 Frun_hooks(int 1, long * 0x0082ebd4) line 3847 + 19 bytes
+ − 939 Ffuncall(int 2, long * 0x0082ebd0) line 3509 + 14 bytes
+ − 940 execute_optimized_program(const unsigned char * 0x01ef2210, int 5, long * 0x01da8e10) line 744 + 16 bytes
+ − 941 funcall_compiled_function(long 31020440, int 2, long * 0x0082eeb8) line 516 + 53 bytes
+ − 942 Ffuncall(int 3, long * 0x0082eeb4) line 3523 + 17 bytes
+ − 943 execute_optimized_program(const unsigned char * 0x0082f09c, int 3, long * 0x01d89390) line 744 + 16 bytes
+ − 944 Fbyte_code(long 31102388, long 30970752, long 7) line 2392 + 38 bytes
+ − 945 Feval(long 31087568) line 3290 + 187 bytes
+ − 946 condition_case_1(long 30961240, long (long)* 0x01087232 Feval(long), long 31087568, long (long, long)* 0x01084764 run_condition_case_handlers(long, long), long 28510180) line 1692 + 7 bytes
+ − 947 condition_case_3(long 31087568, long 28510180, long 30961240) line 1779 + 27 bytes
+ − 948 execute_rare_opcode(long * 0x0082f450, const unsigned char * 0x01ef23ec, int 143) line 1269 + 19 bytes
+ − 949 execute_optimized_program(const unsigned char * 0x01ef2310, int 6, long * 0x01da8f10) line 654 + 17 bytes
+ − 950 funcall_compiled_function(long 31020412, int 1, long * 0x0082f740) line 516 + 53 bytes
+ − 951 Ffuncall(int 2, long * 0x0082f73c) line 3523 + 17 bytes
+ − 952 execute_optimized_program(const unsigned char * 0x020fe650, int 3, long * 0x01d8c490) line 744 + 16 bytes
+ − 953 funcall_compiled_function(long 31020020, int 2, long * 0x0082fa14) line 516 + 53 bytes
+ − 954 Ffuncall(int 3, long * 0x0082fa10) line 3523 + 17 bytes
+ − 955 Fcall_interactively(long 29685180, long 28377092, long 28377092) line 1008 + 22 bytes
+ − 956 Fcommand_execute(long 29685180, long 28377092, long 28377092) line 2929 + 17 bytes
+ − 957 execute_command_event(command_builder * 0x01be1900, long 36626492) line 4048 + 25 bytes
+ − 958 Fdispatch_event(long 36626492) line 4341 + 70 bytes
+ − 959 Fcommand_loop_1() line 582 + 9 bytes
+ − 960 command_loop_1(long 28377092) line 495
+ − 961 condition_case_1(long 28377188, long (long)* 0x01064fb9 command_loop_1(long), long 28377092, long (long, long)* 0x010649d0 cmd_error(long, long), long 28377092) line 1692 + 7 bytes
+ − 962 command_loop_3() line 256 + 35 bytes
+ − 963 command_loop_2(long 28377092) line 269
+ − 964 internal_catch(long 28457612, long (long)* 0x01064b20 command_loop_2(long), long 28377092, int * volatile 0x00000000) line 1317 + 7 bytes
+ − 965 initial_command_loop(long 28377092) line 305 + 25 bytes
+ − 966 STACK_TRACE_EYE_CATCHER(int 1, char * * 0x01b63ff0, char * * 0x01ca5300, int 0) line 2501
+ − 967 main(int 1, char * * 0x01b63ff0, char * * 0x01ca5300) line 2938
+ − 968 XEMACS! mainCRTStartup + 180 bytes
+ − 969 _start() line 171
+ − 970 KERNEL32! BaseProcessStart@4 + 115547 bytes
+ − 971
+ − 972 */
853
+ − 973 int specdepth;
+ − 974
428
+ − 975 if (dont_check_for_quit)
853
+ − 976 return;
428
+ − 977
+ − 978 if (quit_check_signal_happened)
+ − 979 {
1123
+ − 980 /* Since arbitrary Lisp code may be executed (e.g. through a menu
+ − 981 filter, see backtrace directly above), GC might happen,
771
+ − 982 which would majorly fuck a lot of things, e.g. re_match()
+ − 983 [string gets relocated] and lots of other code that's not
+ − 984 prepared to handle GC in QUIT. */
853
+ − 985 specdepth = begin_gc_forbidden ();
428
+ − 986 quit_check_signal_happened = 0;
+ − 987 event_stream_quit_p ();
771
+ − 988 unbind_to (specdepth);
428
+ − 989 }
+ − 990 }
+ − 991
+ − 992
+ − 993
+ − 994 void
+ − 995 init_poll_for_quit (void)
+ − 996 {
+ − 997 #if !defined (SIGIO) && !defined (DONT_POLL_FOR_QUIT)
+ − 998 /* Check for C-g every 1/4 of a second.
+ − 999
+ − 1000 #### This is just a guess. Some investigation will have to be
+ − 1001 done to see what the best value is. The best value is the
+ − 1002 smallest possible value that doesn't cause a significant amount
+ − 1003 of running time to be spent in C-g checking. */
+ − 1004 if (!poll_for_quit_id)
+ − 1005 poll_for_quit_id =
+ − 1006 event_stream_generate_wakeup (NORMAL_QUIT_CHECK_TIMEOUT_MSECS,
+ − 1007 NORMAL_QUIT_CHECK_TIMEOUT_MSECS,
+ − 1008 Qnil, Qnil, 1);
+ − 1009 #endif /* not SIGIO and not DONT_POLL_FOR_QUIT */
+ − 1010 }
+ − 1011
593
+ − 1012 #if 0 /* not used anywhere */
+ − 1013
428
+ − 1014 void
+ − 1015 reset_poll_for_quit (void)
+ − 1016 {
+ − 1017 #if !defined (SIGIO) && !defined (DONT_POLL_FOR_QUIT)
+ − 1018 if (poll_for_quit_id)
+ − 1019 {
+ − 1020 event_stream_disable_wakeup (poll_for_quit_id, 1);
+ − 1021 poll_for_quit_id = 0;
+ − 1022 }
+ − 1023 #endif /* not SIGIO and not DONT_POLL_FOR_QUIT */
+ − 1024 }
+ − 1025
593
+ − 1026 #endif /* 0 */
+ − 1027
853
+ − 1028 #if defined (HAVE_UNIX_PROCESSES) && !defined (SIGCHLD)
428
+ − 1029
+ − 1030 static void
+ − 1031 init_poll_for_sigchld (void)
+ − 1032 {
+ − 1033 /* Check for terminated processes every 1/4 of a second.
+ − 1034
+ − 1035 #### This is just a guess. Some investigation will have to be
+ − 1036 done to see what the best value is. The best value is the
+ − 1037 smallest possible value that doesn't cause a significant amount
+ − 1038 of running time to be spent in process-termination checking.
+ − 1039 */
+ − 1040 poll_for_sigchld_id =
+ − 1041 event_stream_generate_wakeup (NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS,
+ − 1042 NORMAL_SIGCHLD_CHECK_TIMEOUT_MSECS,
+ − 1043 Qnil, Qnil, 1);
+ − 1044 }
+ − 1045
+ − 1046 #endif /* not SIGCHLD */
+ − 1047
+ − 1048
+ − 1049 /************************************************************************/
+ − 1050 /* initialization */
+ − 1051 /************************************************************************/
+ − 1052
+ − 1053 /* If we've been nohup'ed, keep it that way.
+ − 1054 This allows `nohup xemacs &' to work.
+ − 1055 More generally, if a normally fatal signal has been redirected
+ − 1056 to SIG_IGN by our invocation environment, trust the environment.
+ − 1057 This keeps xemacs from being killed by a SIGQUIT intended for a
+ − 1058 different process after having been backgrounded under a
+ − 1059 non-job-control shell! */
+ − 1060 static void
+ − 1061 handle_signal_if_fatal (int signo)
+ − 1062 {
613
+ − 1063 if (EMACS_SIGNAL (signo, fatal_error_signal) == SIG_IGN)
+ − 1064 EMACS_SIGNAL (signo, SIG_IGN);
428
+ − 1065 }
+ − 1066
+ − 1067 void
+ − 1068 init_signals_very_early (void)
+ − 1069 {
+ − 1070 /* Catch all signals that would kill us.
+ − 1071 Don't catch these signals in batch mode if not initialized.
+ − 1072 On some machines, this sets static data that would make
+ − 1073 signal fail to work right when the dumped Emacs is run. */
+ − 1074 if (noninteractive && !initialized)
+ − 1075 return;
+ − 1076
+ − 1077 handle_signal_if_fatal (SIGILL); /* ANSI */
+ − 1078 handle_signal_if_fatal (SIGABRT); /* ANSI */
+ − 1079 handle_signal_if_fatal (SIGFPE); /* ANSI */
+ − 1080 handle_signal_if_fatal (SIGSEGV); /* ANSI */
+ − 1081 handle_signal_if_fatal (SIGTERM); /* ANSI */
+ − 1082
+ − 1083
+ − 1084 #ifdef SIGHUP
+ − 1085 handle_signal_if_fatal (SIGHUP); /* POSIX */
+ − 1086 #endif
+ − 1087 #ifdef SIGQUIT
+ − 1088 handle_signal_if_fatal (SIGQUIT); /* POSIX */
+ − 1089 #endif
+ − 1090 #ifdef SIGTRAP
+ − 1091 handle_signal_if_fatal (SIGTRAP); /* POSIX */
+ − 1092 #endif
+ − 1093 #ifdef SIGUSR1
+ − 1094 handle_signal_if_fatal (SIGUSR1); /* POSIX */
+ − 1095 #endif
+ − 1096 #ifdef SIGUSR2
+ − 1097 handle_signal_if_fatal (SIGUSR2); /* POSIX */
+ − 1098 #endif
+ − 1099 #ifdef SIGPIPE
+ − 1100 handle_signal_if_fatal (SIGPIPE); /* POSIX */
+ − 1101 #endif
+ − 1102 #ifdef SIGALRM
+ − 1103 /* This will get reset later, once we're
+ − 1104 capable of handling it properly. */
+ − 1105 handle_signal_if_fatal (SIGALRM); /* POSIX */
+ − 1106 #endif
+ − 1107
+ − 1108
+ − 1109 #ifdef SIGBUS
+ − 1110 handle_signal_if_fatal (SIGBUS); /* XPG5 */
+ − 1111 #endif
+ − 1112 #ifdef SIGSYS
+ − 1113 handle_signal_if_fatal (SIGSYS); /* XPG5 */
+ − 1114 #endif
+ − 1115 #ifdef SIGXCPU
+ − 1116 handle_signal_if_fatal (SIGXCPU); /* XPG5 */
+ − 1117 #endif
+ − 1118 #ifdef SIGXFSZ
+ − 1119 handle_signal_if_fatal (SIGXFSZ); /* XPG5 */
+ − 1120 #endif
+ − 1121 #ifdef SIGVTALRM
+ − 1122 handle_signal_if_fatal (SIGVTALRM); /* XPG5 */
+ − 1123 #endif
+ − 1124 #ifdef SIGPROF
+ − 1125 /* Messes up the REAL profiler */
+ − 1126 /* handle_signal_if_fatal (SIGPROF); */ /* XPG5 */
+ − 1127 #endif
+ − 1128
+ − 1129
+ − 1130 #ifdef SIGHWE
+ − 1131 handle_signal_if_fatal (SIGHWE);
+ − 1132 #endif
+ − 1133 #ifdef SIGPRE
+ − 1134 handle_signal_if_fatal (SIGPRE);
+ − 1135 #endif
+ − 1136 #ifdef SIGORE
+ − 1137 handle_signal_if_fatal (SIGORE);
+ − 1138 #endif
+ − 1139 #ifdef SIGUME
+ − 1140 handle_signal_if_fatal (SIGUME);
+ − 1141 #endif
+ − 1142 #ifdef SIGDLK
+ − 1143 handle_signal_if_fatal (SIGDLK);
+ − 1144 #endif
+ − 1145 #ifdef SIGCPULIM
+ − 1146 handle_signal_if_fatal (SIGCPULIM);
+ − 1147 #endif
+ − 1148 #ifdef SIGIOT
+ − 1149 handle_signal_if_fatal (SIGIOT);
+ − 1150 #endif
+ − 1151 #ifdef SIGEMT
+ − 1152 handle_signal_if_fatal (SIGEMT);
+ − 1153 #endif
+ − 1154 #ifdef SIGLOST
+ − 1155 handle_signal_if_fatal (SIGLOST);
+ − 1156 #endif
+ − 1157 #ifdef SIGSTKFLT /* coprocessor stack fault under Linux */
+ − 1158 handle_signal_if_fatal (SIGSTKFLT);
+ − 1159 #endif
+ − 1160 #ifdef SIGUNUSED /* exists under Linux, and will kill process! */
+ − 1161 handle_signal_if_fatal (SIGUNUSED);
+ − 1162 #endif
+ − 1163
+ − 1164 #ifdef AIX
+ − 1165 /* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU. */
+ − 1166 #ifndef _I386
+ − 1167 handle_signal_if_fatal (SIGIOINT);
+ − 1168 #endif
+ − 1169 handle_signal_if_fatal (SIGGRANT);
+ − 1170 handle_signal_if_fatal (SIGRETRACT);
+ − 1171 handle_signal_if_fatal (SIGSOUND);
+ − 1172 handle_signal_if_fatal (SIGMSG);
+ − 1173 #endif /* AIX */
+ − 1174
+ − 1175 #ifdef SIGDANGER
+ − 1176 /* This just means available memory is getting low. */
613
+ − 1177 EMACS_SIGNAL (SIGDANGER, memory_warning_signal);
428
+ − 1178 #endif
+ − 1179 }
+ − 1180
+ − 1181 void
+ − 1182 syms_of_signal (void)
+ − 1183 {
+ − 1184 DEFSUBR (Fwaiting_for_user_input_p);
+ − 1185 }
+ − 1186
+ − 1187 void
+ − 1188 init_interrupts_late (void)
+ − 1189 {
+ − 1190 if (!noninteractive)
+ − 1191 {
613
+ − 1192 EMACS_SIGNAL (SIGINT, interrupt_signal);
428
+ − 1193 #ifdef HAVE_TERMIO
+ − 1194 /* On systems with TERMIO, C-g is set up for both SIGINT and SIGQUIT
+ − 1195 and we can't tell which one it will give us. */
613
+ − 1196 EMACS_SIGNAL (SIGQUIT, interrupt_signal);
428
+ − 1197 #endif /* HAVE_TERMIO */
+ − 1198 init_async_timeouts ();
+ − 1199 #ifdef SIGIO
613
+ − 1200 EMACS_SIGNAL (SIGIO, input_available_signal);
428
+ − 1201 # ifdef SIGPOLL /* XPG5 */
+ − 1202 /* Some systems (e.g. Motorola SVR4) losingly have different
+ − 1203 values for SIGIO and SIGPOLL, and send SIGPOLL instead of
+ − 1204 SIGIO. On those same systems, an uncaught SIGPOLL kills the
+ − 1205 process. */
613
+ − 1206 EMACS_SIGNAL (SIGPOLL, input_available_signal);
428
+ − 1207 # endif
+ − 1208 #elif !defined (DONT_POLL_FOR_QUIT)
+ − 1209 init_poll_for_quit ();
+ − 1210 #endif
+ − 1211 }
+ − 1212
853
+ − 1213 #if defined (HAVE_UNIX_PROCESSES) && !defined (SIGCHLD)
428
+ − 1214 init_poll_for_sigchld ();
+ − 1215 #endif
+ − 1216
+ − 1217 EMACS_UNBLOCK_ALL_SIGNALS ();
+ − 1218
+ − 1219 interrupts_initted = 1;
+ − 1220 }
+ − 1221