diff options
| author | Paul Eggert | 2012-09-05 14:33:53 -0700 |
|---|---|---|
| committer | Paul Eggert | 2012-09-05 14:33:53 -0700 |
| commit | 20ef56dbc88f517ebf60d89577fc89870d9fe888 (patch) | |
| tree | e93c0bc49e89e86836575b2b4443c699a237621d /src | |
| parent | a4e6c042f8f66c47209d76d863adbf5ea3f84a96 (diff) | |
| download | emacs-20ef56dbc88f517ebf60d89577fc89870d9fe888.tar.gz emacs-20ef56dbc88f517ebf60d89577fc89870d9fe888.zip | |
Fix race conditions with signal handlers and errno.
Be more systematic about preserving errno whenever a signal
handler returns, even if it's not in the main thread. Do this by
renaming signal handlers to distinguish between signal delivery
and signal handling. All uses changed.
* atimer.c (deliver_alarm_signal): Rename from alarm_signal_handler.
* data.c (deliver_arith_signal): Rename from arith_error.
* dispnew.c (deliver_window_change_signal): Rename from
window_change_signal.
* emacs.c (deliver_error_signal): Rename from fatal_error_signal.
(deliver_danger_signal) [SIGDANGER]: Rename from memory_warning_signal.
* keyboard.c (deliver_input_available_signal): Rename from
input_available_signal.
(deliver_user_signal): Rename from handle_user_signal.
(deliver_interrupt_signal): Rename from interrupt_signal.
* process.c (deliver_pipe_signal): Rename from send_process_trap.
(deliver_child_signal): Rename from sigchld_handler.
* atimer.c (handle_alarm_signal):
* data.c (handle_arith_signal):
* dispnew.c (handle_window_change_signal):
* emacs.c (handle_fatal_signal, handle_danger_signal):
* keyboard.c (handle_input_available_signal):
* keyboard.c (handle_user_signal, handle_interrupt_signal):
* process.c (handle_pipe_signal, handle_child_signal):
New functions, with the actual signal-handling code taken from the
original respective signal handlers, sans the sporadic attempts to
preserve errno, since that's now done by handle_on_main_thread.
* atimer.c (alarm_signal_handler): Remove unnecessary decl.
* emacs.c, floatfns.c, lisp.h: Remove unused FLOAT_CATCH_SIGKILL cruft.
* emacs.c (main_thread) [FORWARD_SIGNAL_TO_MAIN_THREAD]:
Move to sysdep.c.
(main) [FORWARD_SIGNAL_TO_MAIN_THREAD]:
Move initialization of main_thread to sysdep.c's init_signals.
* process.c (waitpid) [!WNOHANG]: #define to wait; that's good enough for
our usage, and simplifies the mainline code.
(record_child_status_change): New static function, as a helper
for handle_child_signal, and with most of the old child handler's
contents.
(CAN_HANDLE_MULTIPLE_CHILDREN): New constant.
(handle_child_signal): Use the above.
* sysdep.c (main_thread) [FORWARD_SIGNAL_TO_MAIN_THREAD]:
Moved here from emacs.c.
(init_signals) [FORWARD_SIGNAL_TO_MAIN_THREAD]: Initialize it;
code moved here from emacs.c's main function.
* sysdep.c, syssignal.h (handle_on_main_thread): New function,
replacing the old SIGNAL_THREAD_CHECK. All uses changed. This
lets callers save and restore errno properly.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 50 | ||||
| -rw-r--r-- | src/atimer.c | 24 | ||||
| -rw-r--r-- | src/data.c | 17 | ||||
| -rw-r--r-- | src/dispnew.c | 20 | ||||
| -rw-r--r-- | src/emacs.c | 98 | ||||
| -rw-r--r-- | src/floatfns.c | 35 | ||||
| -rw-r--r-- | src/keyboard.c | 54 | ||||
| -rw-r--r-- | src/lisp.h | 3 | ||||
| -rw-r--r-- | src/process.c | 256 | ||||
| -rw-r--r-- | src/sysdep.c | 38 | ||||
| -rw-r--r-- | src/syssignal.h | 23 |
11 files changed, 324 insertions, 294 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 96e3fdd5b45..24d290e163d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,53 @@ | |||
| 1 | 2012-09-05 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix race conditions with signal handlers and errno. | ||
| 4 | Be more systematic about preserving errno whenever a signal | ||
| 5 | handler returns, even if it's not in the main thread. Do this by | ||
| 6 | renaming signal handlers to distinguish between signal delivery | ||
| 7 | and signal handling. All uses changed. | ||
| 8 | * atimer.c (deliver_alarm_signal): Rename from alarm_signal_handler. | ||
| 9 | * data.c (deliver_arith_signal): Rename from arith_error. | ||
| 10 | * dispnew.c (deliver_window_change_signal): Rename from | ||
| 11 | window_change_signal. | ||
| 12 | * emacs.c (deliver_error_signal): Rename from fatal_error_signal. | ||
| 13 | (deliver_danger_signal) [SIGDANGER]: Rename from memory_warning_signal. | ||
| 14 | * keyboard.c (deliver_input_available_signal): Rename from | ||
| 15 | input_available_signal. | ||
| 16 | (deliver_user_signal): Rename from handle_user_signal. | ||
| 17 | (deliver_interrupt_signal): Rename from interrupt_signal. | ||
| 18 | * process.c (deliver_pipe_signal): Rename from send_process_trap. | ||
| 19 | (deliver_child_signal): Rename from sigchld_handler. | ||
| 20 | * atimer.c (handle_alarm_signal): | ||
| 21 | * data.c (handle_arith_signal): | ||
| 22 | * dispnew.c (handle_window_change_signal): | ||
| 23 | * emacs.c (handle_fatal_signal, handle_danger_signal): | ||
| 24 | * keyboard.c (handle_input_available_signal): | ||
| 25 | * keyboard.c (handle_user_signal, handle_interrupt_signal): | ||
| 26 | * process.c (handle_pipe_signal, handle_child_signal): | ||
| 27 | New functions, with the actual signal-handling code taken from the | ||
| 28 | original respective signal handlers, sans the sporadic attempts to | ||
| 29 | preserve errno, since that's now done by handle_on_main_thread. | ||
| 30 | * atimer.c (alarm_signal_handler): Remove unnecessary decl. | ||
| 31 | * emacs.c, floatfns.c, lisp.h: Remove unused FLOAT_CATCH_SIGKILL cruft. | ||
| 32 | * emacs.c (main_thread) [FORWARD_SIGNAL_TO_MAIN_THREAD]: | ||
| 33 | Move to sysdep.c. | ||
| 34 | (main) [FORWARD_SIGNAL_TO_MAIN_THREAD]: | ||
| 35 | Move initialization of main_thread to sysdep.c's init_signals. | ||
| 36 | * process.c (waitpid) [!WNOHANG]: #define to wait; that's good enough for | ||
| 37 | our usage, and simplifies the mainline code. | ||
| 38 | (record_child_status_change): New static function, as a helper | ||
| 39 | for handle_child_signal, and with most of the old child handler's | ||
| 40 | contents. | ||
| 41 | (CAN_HANDLE_MULTIPLE_CHILDREN): New constant. | ||
| 42 | (handle_child_signal): Use the above. | ||
| 43 | * sysdep.c (main_thread) [FORWARD_SIGNAL_TO_MAIN_THREAD]: | ||
| 44 | Moved here from emacs.c. | ||
| 45 | (init_signals) [FORWARD_SIGNAL_TO_MAIN_THREAD]: Initialize it; | ||
| 46 | code moved here from emacs.c's main function. | ||
| 47 | * sysdep.c, syssignal.h (handle_on_main_thread): New function, | ||
| 48 | replacing the old SIGNAL_THREAD_CHECK. All uses changed. This | ||
| 49 | lets callers save and restore errno properly. | ||
| 50 | |||
| 1 | 2012-09-05 Dmitry Antipov <dmantipov@yandex.ru> | 51 | 2012-09-05 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 52 | ||
| 3 | Remove redundant or unused things here and there. | 53 | Remove redundant or unused things here and there. |
diff --git a/src/atimer.c b/src/atimer.c index eb3136ae55d..060dead9b17 100644 --- a/src/atimer.c +++ b/src/atimer.c | |||
| @@ -41,7 +41,7 @@ static struct atimer *stopped_atimers; | |||
| 41 | 41 | ||
| 42 | static struct atimer *atimers; | 42 | static struct atimer *atimers; |
| 43 | 43 | ||
| 44 | /* Non-zero means alarm_signal_handler has found ripe timers but | 44 | /* Non-zero means alarm signal handler has found ripe timers but |
| 45 | interrupt_input_blocked was non-zero. In this case, timer | 45 | interrupt_input_blocked was non-zero. In this case, timer |
| 46 | functions are not called until the next UNBLOCK_INPUT because timer | 46 | functions are not called until the next UNBLOCK_INPUT because timer |
| 47 | functions are expected to call X, and X cannot be assumed to be | 47 | functions are expected to call X, and X cannot be assumed to be |
| @@ -60,8 +60,6 @@ static void set_alarm (void); | |||
| 60 | static void schedule_atimer (struct atimer *); | 60 | static void schedule_atimer (struct atimer *); |
| 61 | static struct atimer *append_atimer_lists (struct atimer *, | 61 | static struct atimer *append_atimer_lists (struct atimer *, |
| 62 | struct atimer *); | 62 | struct atimer *); |
| 63 | static void alarm_signal_handler (int signo); | ||
| 64 | |||
| 65 | 63 | ||
| 66 | /* Start a new atimer of type TYPE. TIME specifies when the timer is | 64 | /* Start a new atimer of type TYPE. TIME specifies when the timer is |
| 67 | ripe. FN is the function to call when the timer fires. | 65 | ripe. FN is the function to call when the timer fires. |
| @@ -374,13 +372,9 @@ run_timers (void) | |||
| 374 | /* Signal handler for SIGALRM. SIGNO is the signal number, i.e. | 372 | /* Signal handler for SIGALRM. SIGNO is the signal number, i.e. |
| 375 | SIGALRM. */ | 373 | SIGALRM. */ |
| 376 | 374 | ||
| 377 | void | 375 | static void |
| 378 | alarm_signal_handler (int signo) | 376 | handle_alarm_signal (int sig) |
| 379 | { | 377 | { |
| 380 | #ifndef SYNC_INPUT | ||
| 381 | SIGNAL_THREAD_CHECK (signo); | ||
| 382 | #endif | ||
| 383 | |||
| 384 | pending_atimers = 1; | 378 | pending_atimers = 1; |
| 385 | #ifdef SYNC_INPUT | 379 | #ifdef SYNC_INPUT |
| 386 | pending_signals = 1; | 380 | pending_signals = 1; |
| @@ -389,8 +383,14 @@ alarm_signal_handler (int signo) | |||
| 389 | #endif | 383 | #endif |
| 390 | } | 384 | } |
| 391 | 385 | ||
| 386 | static void | ||
| 387 | deliver_alarm_signal (int sig) | ||
| 388 | { | ||
| 389 | handle_on_main_thread (sig, handle_alarm_signal); | ||
| 390 | } | ||
| 391 | |||
| 392 | 392 | ||
| 393 | /* Call alarm_signal_handler for pending timers. */ | 393 | /* Call alarm signal handler for pending timers. */ |
| 394 | 394 | ||
| 395 | void | 395 | void |
| 396 | do_pending_atimers (void) | 396 | do_pending_atimers (void) |
| @@ -412,7 +412,7 @@ turn_on_atimers (bool on) | |||
| 412 | { | 412 | { |
| 413 | if (on) | 413 | if (on) |
| 414 | { | 414 | { |
| 415 | signal (SIGALRM, alarm_signal_handler); | 415 | signal (SIGALRM, deliver_alarm_signal); |
| 416 | set_alarm (); | 416 | set_alarm (); |
| 417 | } | 417 | } |
| 418 | else | 418 | else |
| @@ -426,5 +426,5 @@ init_atimer (void) | |||
| 426 | free_atimers = stopped_atimers = atimers = NULL; | 426 | free_atimers = stopped_atimers = atimers = NULL; |
| 427 | pending_atimers = 0; | 427 | pending_atimers = 0; |
| 428 | /* pending_signals is initialized in init_keyboard.*/ | 428 | /* pending_signals is initialized in init_keyboard.*/ |
| 429 | signal (SIGALRM, alarm_signal_handler); | 429 | signal (SIGALRM, deliver_alarm_signal); |
| 430 | } | 430 | } |
diff --git a/src/data.c b/src/data.c index 415a8962350..6151d815b29 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -3207,18 +3207,19 @@ syms_of_data (void) | |||
| 3207 | XSYMBOL (intern_c_string ("most-negative-fixnum"))->constant = 1; | 3207 | XSYMBOL (intern_c_string ("most-negative-fixnum"))->constant = 1; |
| 3208 | } | 3208 | } |
| 3209 | 3209 | ||
| 3210 | #ifndef FORWARD_SIGNAL_TO_MAIN_THREAD | 3210 | static _Noreturn void |
| 3211 | _Noreturn | 3211 | handle_arith_signal (int sig) |
| 3212 | #endif | ||
| 3213 | static void | ||
| 3214 | arith_error (int signo) | ||
| 3215 | { | 3212 | { |
| 3216 | sigsetmask (SIGEMPTYMASK); | 3213 | sigsetmask (SIGEMPTYMASK); |
| 3217 | |||
| 3218 | SIGNAL_THREAD_CHECK (signo); | ||
| 3219 | xsignal0 (Qarith_error); | 3214 | xsignal0 (Qarith_error); |
| 3220 | } | 3215 | } |
| 3221 | 3216 | ||
| 3217 | static void | ||
| 3218 | deliver_arith_signal (int sig) | ||
| 3219 | { | ||
| 3220 | handle_on_main_thread (sig, handle_arith_signal); | ||
| 3221 | } | ||
| 3222 | |||
| 3222 | void | 3223 | void |
| 3223 | init_data (void) | 3224 | init_data (void) |
| 3224 | { | 3225 | { |
| @@ -3230,5 +3231,5 @@ init_data (void) | |||
| 3230 | if (!initialized) | 3231 | if (!initialized) |
| 3231 | return; | 3232 | return; |
| 3232 | #endif /* CANNOT_DUMP */ | 3233 | #endif /* CANNOT_DUMP */ |
| 3233 | signal (SIGFPE, arith_error); | 3234 | signal (SIGFPE, deliver_arith_signal); |
| 3234 | } | 3235 | } |
diff --git a/src/dispnew.c b/src/dispnew.c index 17e6c85ac75..e02b33000d8 100644 --- a/src/dispnew.c +++ b/src/dispnew.c | |||
| @@ -5552,17 +5552,15 @@ marginal_area_string (struct window *w, enum window_part part, | |||
| 5552 | 5552 | ||
| 5553 | #ifdef SIGWINCH | 5553 | #ifdef SIGWINCH |
| 5554 | 5554 | ||
| 5555 | static void deliver_window_change_signal (int); | ||
| 5556 | |||
| 5555 | static void | 5557 | static void |
| 5556 | window_change_signal (int signalnum) /* If we don't have an argument, */ | 5558 | handle_window_change_signal (int sig) |
| 5557 | /* some compilers complain in signal calls. */ | ||
| 5558 | { | 5559 | { |
| 5559 | int width, height; | 5560 | int width, height; |
| 5560 | int old_errno = errno; | ||
| 5561 | |||
| 5562 | struct tty_display_info *tty; | 5561 | struct tty_display_info *tty; |
| 5563 | 5562 | ||
| 5564 | signal (SIGWINCH, window_change_signal); | 5563 | signal (SIGWINCH, deliver_window_change_signal); |
| 5565 | SIGNAL_THREAD_CHECK (signalnum); | ||
| 5566 | 5564 | ||
| 5567 | /* The frame size change obviously applies to a single | 5565 | /* The frame size change obviously applies to a single |
| 5568 | termcap-controlled terminal, but we can't decide which. | 5566 | termcap-controlled terminal, but we can't decide which. |
| @@ -5591,8 +5589,12 @@ window_change_signal (int signalnum) /* If we don't have an argument, */ | |||
| 5591 | change_frame_size (XFRAME (frame), height, width, 0, 1, 0); | 5589 | change_frame_size (XFRAME (frame), height, width, 0, 1, 0); |
| 5592 | } | 5590 | } |
| 5593 | } | 5591 | } |
| 5592 | } | ||
| 5594 | 5593 | ||
| 5595 | errno = old_errno; | 5594 | static void |
| 5595 | deliver_window_change_signal (int sig) | ||
| 5596 | { | ||
| 5597 | handle_on_main_thread (sig, handle_window_change_signal); | ||
| 5596 | } | 5598 | } |
| 5597 | #endif /* SIGWINCH */ | 5599 | #endif /* SIGWINCH */ |
| 5598 | 5600 | ||
| @@ -5604,7 +5606,7 @@ window_change_signal (int signalnum) /* If we don't have an argument, */ | |||
| 5604 | void | 5606 | void |
| 5605 | do_pending_window_change (bool safe) | 5607 | do_pending_window_change (bool safe) |
| 5606 | { | 5608 | { |
| 5607 | /* If window_change_signal should have run before, run it now. */ | 5609 | /* If window change signal handler should have run before, run it now. */ |
| 5608 | if (redisplaying_p && !safe) | 5610 | if (redisplaying_p && !safe) |
| 5609 | return; | 5611 | return; |
| 5610 | 5612 | ||
| @@ -6173,7 +6175,7 @@ init_display (void) | |||
| 6173 | #ifndef CANNOT_DUMP | 6175 | #ifndef CANNOT_DUMP |
| 6174 | if (initialized) | 6176 | if (initialized) |
| 6175 | #endif /* CANNOT_DUMP */ | 6177 | #endif /* CANNOT_DUMP */ |
| 6176 | signal (SIGWINCH, window_change_signal); | 6178 | signal (SIGWINCH, deliver_window_change_signal); |
| 6177 | #endif /* SIGWINCH */ | 6179 | #endif /* SIGWINCH */ |
| 6178 | 6180 | ||
| 6179 | /* If running as a daemon, no need to initialize any frames/terminal. */ | 6181 | /* If running as a daemon, no need to initialize any frames/terminal. */ |
diff --git a/src/emacs.c b/src/emacs.c index 18f249dc899..fc92b30af26 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -275,14 +275,6 @@ static int fatal_error_code; | |||
| 275 | /* True if handling a fatal error already. */ | 275 | /* True if handling a fatal error already. */ |
| 276 | bool fatal_error_in_progress; | 276 | bool fatal_error_in_progress; |
| 277 | 277 | ||
| 278 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD | ||
| 279 | /* When compiled with GTK and running under Gnome, | ||
| 280 | multiple threads may be created. Keep track of our main | ||
| 281 | thread to make sure signals are delivered to it (see syssignal.h). */ | ||
| 282 | |||
| 283 | pthread_t main_thread; | ||
| 284 | #endif | ||
| 285 | |||
| 286 | #ifdef HAVE_NS | 278 | #ifdef HAVE_NS |
| 287 | /* NS autrelease pool, for memory management. */ | 279 | /* NS autrelease pool, for memory management. */ |
| 288 | static void *ns_pool; | 280 | static void *ns_pool; |
| @@ -291,16 +283,18 @@ static void *ns_pool; | |||
| 291 | 283 | ||
| 292 | 284 | ||
| 293 | /* Handle bus errors, invalid instruction, etc. */ | 285 | /* Handle bus errors, invalid instruction, etc. */ |
| 294 | #ifndef FLOAT_CATCH_SIGILL | 286 | static void |
| 295 | static | 287 | handle_fatal_signal (int sig) |
| 296 | #endif | ||
| 297 | void | ||
| 298 | fatal_error_signal (int sig) | ||
| 299 | { | 288 | { |
| 300 | SIGNAL_THREAD_CHECK (sig); | ||
| 301 | fatal_error_backtrace (sig, 10); | 289 | fatal_error_backtrace (sig, 10); |
| 302 | } | 290 | } |
| 303 | 291 | ||
| 292 | static void | ||
| 293 | deliver_fatal_signal (int sig) | ||
| 294 | { | ||
| 295 | handle_on_main_thread (sig, handle_fatal_signal); | ||
| 296 | } | ||
| 297 | |||
| 304 | /* Report a fatal error due to signal SIG, output a backtrace of at | 298 | /* Report a fatal error due to signal SIG, output a backtrace of at |
| 305 | most BACKTRACE_LIMIT lines, and exit. */ | 299 | most BACKTRACE_LIMIT lines, and exit. */ |
| 306 | _Noreturn void | 300 | _Noreturn void |
| @@ -340,17 +334,23 @@ fatal_error_backtrace (int sig, int backtrace_limit) | |||
| 340 | #ifdef SIGDANGER | 334 | #ifdef SIGDANGER |
| 341 | 335 | ||
| 342 | /* Handler for SIGDANGER. */ | 336 | /* Handler for SIGDANGER. */ |
| 343 | void | 337 | static void deliver_danger_signal (int); |
| 344 | memory_warning_signal (int sig) | ||
| 345 | { | ||
| 346 | signal (sig, memory_warning_signal); | ||
| 347 | SIGNAL_THREAD_CHECK (sig); | ||
| 348 | 338 | ||
| 339 | static void | ||
| 340 | handle_danger_signal (int sig) | ||
| 341 | { | ||
| 342 | signal (sig, deliver_danger_signal); | ||
| 349 | malloc_warning ("Operating system warns that virtual memory is running low.\n"); | 343 | malloc_warning ("Operating system warns that virtual memory is running low.\n"); |
| 350 | 344 | ||
| 351 | /* It might be unsafe to call do_auto_save now. */ | 345 | /* It might be unsafe to call do_auto_save now. */ |
| 352 | force_auto_save_soon (); | 346 | force_auto_save_soon (); |
| 353 | } | 347 | } |
| 348 | |||
| 349 | static void | ||
| 350 | deliver_danger_signal (int sig) | ||
| 351 | { | ||
| 352 | handle_on_main_thread (sig, handle_danger_signal); | ||
| 353 | } | ||
| 354 | #endif | 354 | #endif |
| 355 | 355 | ||
| 356 | /* Code for dealing with Lisp access to the Unix command line. */ | 356 | /* Code for dealing with Lisp access to the Unix command line. */ |
| @@ -851,10 +851,6 @@ main (int argc, char **argv) | |||
| 851 | # endif /* not SYNC_INPUT */ | 851 | # endif /* not SYNC_INPUT */ |
| 852 | #endif /* not SYSTEM_MALLOC */ | 852 | #endif /* not SYSTEM_MALLOC */ |
| 853 | 853 | ||
| 854 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD | ||
| 855 | main_thread = pthread_self (); | ||
| 856 | #endif /* FORWARD_SIGNAL_TO_MAIN_THREAD */ | ||
| 857 | |||
| 858 | #if defined (MSDOS) || defined (WINDOWSNT) | 854 | #if defined (MSDOS) || defined (WINDOWSNT) |
| 859 | /* We do all file input/output as binary files. When we need to translate | 855 | /* We do all file input/output as binary files. When we need to translate |
| 860 | newlines, we do that manually. */ | 856 | newlines, we do that manually. */ |
| @@ -1120,7 +1116,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1120 | That makes nohup work. */ | 1116 | That makes nohup work. */ |
| 1121 | if (! noninteractive | 1117 | if (! noninteractive |
| 1122 | || signal (SIGHUP, SIG_IGN) != SIG_IGN) | 1118 | || signal (SIGHUP, SIG_IGN) != SIG_IGN) |
| 1123 | signal (SIGHUP, fatal_error_signal); | 1119 | signal (SIGHUP, deliver_fatal_signal); |
| 1124 | sigunblock (sigmask (SIGHUP)); | 1120 | sigunblock (sigmask (SIGHUP)); |
| 1125 | } | 1121 | } |
| 1126 | 1122 | ||
| @@ -1135,9 +1131,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1135 | /* Don't catch these signals in batch mode if dumping. | 1131 | /* Don't catch these signals in batch mode if dumping. |
| 1136 | On some machines, this sets static data that would make | 1132 | On some machines, this sets static data that would make |
| 1137 | signal fail to work right when the dumped Emacs is run. */ | 1133 | signal fail to work right when the dumped Emacs is run. */ |
| 1138 | signal (SIGQUIT, fatal_error_signal); | 1134 | signal (SIGQUIT, deliver_fatal_signal); |
| 1139 | signal (SIGILL, fatal_error_signal); | 1135 | signal (SIGILL, deliver_fatal_signal); |
| 1140 | signal (SIGTRAP, fatal_error_signal); | 1136 | signal (SIGTRAP, deliver_fatal_signal); |
| 1141 | #ifdef SIGUSR1 | 1137 | #ifdef SIGUSR1 |
| 1142 | add_user_signal (SIGUSR1, "sigusr1"); | 1138 | add_user_signal (SIGUSR1, "sigusr1"); |
| 1143 | #endif | 1139 | #endif |
| @@ -1145,68 +1141,68 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1145 | add_user_signal (SIGUSR2, "sigusr2"); | 1141 | add_user_signal (SIGUSR2, "sigusr2"); |
| 1146 | #endif | 1142 | #endif |
| 1147 | #ifdef SIGABRT | 1143 | #ifdef SIGABRT |
| 1148 | signal (SIGABRT, fatal_error_signal); | 1144 | signal (SIGABRT, deliver_fatal_signal); |
| 1149 | #endif | 1145 | #endif |
| 1150 | #ifdef SIGHWE | 1146 | #ifdef SIGHWE |
| 1151 | signal (SIGHWE, fatal_error_signal); | 1147 | signal (SIGHWE, deliver_fatal_signal); |
| 1152 | #endif | 1148 | #endif |
| 1153 | #ifdef SIGPRE | 1149 | #ifdef SIGPRE |
| 1154 | signal (SIGPRE, fatal_error_signal); | 1150 | signal (SIGPRE, deliver_fatal_signal); |
| 1155 | #endif | 1151 | #endif |
| 1156 | #ifdef SIGORE | 1152 | #ifdef SIGORE |
| 1157 | signal (SIGORE, fatal_error_signal); | 1153 | signal (SIGORE, deliver_fatal_signal); |
| 1158 | #endif | 1154 | #endif |
| 1159 | #ifdef SIGUME | 1155 | #ifdef SIGUME |
| 1160 | signal (SIGUME, fatal_error_signal); | 1156 | signal (SIGUME, deliver_fatal_signal); |
| 1161 | #endif | 1157 | #endif |
| 1162 | #ifdef SIGDLK | 1158 | #ifdef SIGDLK |
| 1163 | signal (SIGDLK, fatal_error_signal); | 1159 | signal (SIGDLK, deliver_fatal_signal); |
| 1164 | #endif | 1160 | #endif |
| 1165 | #ifdef SIGCPULIM | 1161 | #ifdef SIGCPULIM |
| 1166 | signal (SIGCPULIM, fatal_error_signal); | 1162 | signal (SIGCPULIM, deliver_fatal_signal); |
| 1167 | #endif | 1163 | #endif |
| 1168 | #ifdef SIGIOT | 1164 | #ifdef SIGIOT |
| 1169 | /* This is missing on some systems - OS/2, for example. */ | 1165 | /* This is missing on some systems - OS/2, for example. */ |
| 1170 | signal (SIGIOT, fatal_error_signal); | 1166 | signal (SIGIOT, deliver_fatal_signal); |
| 1171 | #endif | 1167 | #endif |
| 1172 | #ifdef SIGEMT | 1168 | #ifdef SIGEMT |
| 1173 | signal (SIGEMT, fatal_error_signal); | 1169 | signal (SIGEMT, deliver_fatal_signal); |
| 1174 | #endif | 1170 | #endif |
| 1175 | signal (SIGFPE, fatal_error_signal); | 1171 | signal (SIGFPE, deliver_fatal_signal); |
| 1176 | #ifdef SIGBUS | 1172 | #ifdef SIGBUS |
| 1177 | signal (SIGBUS, fatal_error_signal); | 1173 | signal (SIGBUS, deliver_fatal_signal); |
| 1178 | #endif | 1174 | #endif |
| 1179 | signal (SIGSEGV, fatal_error_signal); | 1175 | signal (SIGSEGV, deliver_fatal_signal); |
| 1180 | #ifdef SIGSYS | 1176 | #ifdef SIGSYS |
| 1181 | signal (SIGSYS, fatal_error_signal); | 1177 | signal (SIGSYS, deliver_fatal_signal); |
| 1182 | #endif | 1178 | #endif |
| 1183 | /* May need special treatment on MS-Windows. See | 1179 | /* May need special treatment on MS-Windows. See |
| 1184 | http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01062.html | 1180 | http://lists.gnu.org/archive/html/emacs-devel/2010-09/msg01062.html |
| 1185 | Please update the doc of kill-emacs, kill-emacs-hook, and | 1181 | Please update the doc of kill-emacs, kill-emacs-hook, and |
| 1186 | NEWS if you change this. | 1182 | NEWS if you change this. |
| 1187 | */ | 1183 | */ |
| 1188 | if (noninteractive) signal (SIGINT, fatal_error_signal); | 1184 | if (noninteractive) signal (SIGINT, deliver_fatal_signal); |
| 1189 | signal (SIGTERM, fatal_error_signal); | 1185 | signal (SIGTERM, deliver_fatal_signal); |
| 1190 | #ifdef SIGXCPU | 1186 | #ifdef SIGXCPU |
| 1191 | signal (SIGXCPU, fatal_error_signal); | 1187 | signal (SIGXCPU, deliver_fatal_signal); |
| 1192 | #endif | 1188 | #endif |
| 1193 | #ifdef SIGXFSZ | 1189 | #ifdef SIGXFSZ |
| 1194 | signal (SIGXFSZ, fatal_error_signal); | 1190 | signal (SIGXFSZ, deliver_fatal_signal); |
| 1195 | #endif /* SIGXFSZ */ | 1191 | #endif /* SIGXFSZ */ |
| 1196 | 1192 | ||
| 1197 | #ifdef SIGDANGER | 1193 | #ifdef SIGDANGER |
| 1198 | /* This just means available memory is getting low. */ | 1194 | /* This just means available memory is getting low. */ |
| 1199 | signal (SIGDANGER, memory_warning_signal); | 1195 | signal (SIGDANGER, deliver_danger_signal); |
| 1200 | #endif | 1196 | #endif |
| 1201 | 1197 | ||
| 1202 | #ifdef AIX | 1198 | #ifdef AIX |
| 1203 | /* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU. */ | 1199 | /* 20 is SIGCHLD, 21 is SIGTTIN, 22 is SIGTTOU. */ |
| 1204 | signal (SIGXCPU, fatal_error_signal); | 1200 | signal (SIGXCPU, deliver_fatal_signal); |
| 1205 | signal (SIGIOINT, fatal_error_signal); | 1201 | signal (SIGIOINT, deliver_fatal_signal); |
| 1206 | signal (SIGGRANT, fatal_error_signal); | 1202 | signal (SIGGRANT, deliver_fatal_signal); |
| 1207 | signal (SIGRETRACT, fatal_error_signal); | 1203 | signal (SIGRETRACT, deliver_fatal_signal); |
| 1208 | signal (SIGSOUND, fatal_error_signal); | 1204 | signal (SIGSOUND, deliver_fatal_signal); |
| 1209 | signal (SIGMSG, fatal_error_signal); | 1205 | signal (SIGMSG, deliver_fatal_signal); |
| 1210 | #endif /* AIX */ | 1206 | #endif /* AIX */ |
| 1211 | } | 1207 | } |
| 1212 | 1208 | ||
diff --git a/src/floatfns.c b/src/floatfns.c index 706fe7ae1a0..f59cf58228a 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -37,9 +37,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 37 | Define FLOAT_CHECK_ERRNO if the float library routines set errno. | 37 | Define FLOAT_CHECK_ERRNO if the float library routines set errno. |
| 38 | This has no effect if HAVE_MATHERR is defined. | 38 | This has no effect if HAVE_MATHERR is defined. |
| 39 | 39 | ||
| 40 | Define FLOAT_CATCH_SIGILL if the float library routines signal SIGILL. | ||
| 41 | (What systems actually do this? Please let us know.) | ||
| 42 | |||
| 43 | Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by | 40 | Define FLOAT_CHECK_DOMAIN if the float library doesn't handle errors by |
| 44 | either setting errno, or signaling SIGFPE/SIGILL. Otherwise, domain and | 41 | either setting errno, or signaling SIGFPE/SIGILL. Otherwise, domain and |
| 45 | range checking will happen before calling the float routines. This has | 42 | range checking will happen before calling the float routines. This has |
| @@ -99,10 +96,6 @@ extern double logb (double); | |||
| 99 | # include <errno.h> | 96 | # include <errno.h> |
| 100 | #endif | 97 | #endif |
| 101 | 98 | ||
| 102 | #ifdef FLOAT_CATCH_SIGILL | ||
| 103 | static void float_error (); | ||
| 104 | #endif | ||
| 105 | |||
| 106 | /* True while executing in floating point. | 99 | /* True while executing in floating point. |
| 107 | This tells float_error what to do. */ | 100 | This tells float_error what to do. */ |
| 108 | 101 | ||
| @@ -947,31 +940,6 @@ Rounds the value toward zero. */) | |||
| 947 | return make_float (d); | 940 | return make_float (d); |
| 948 | } | 941 | } |
| 949 | 942 | ||
| 950 | #ifdef FLOAT_CATCH_SIGILL | ||
| 951 | static void | ||
| 952 | float_error (int signo) | ||
| 953 | { | ||
| 954 | if (! in_float) | ||
| 955 | fatal_error_signal (signo); | ||
| 956 | |||
| 957 | #ifdef BSD_SYSTEM | ||
| 958 | sigsetmask (SIGEMPTYMASK); | ||
| 959 | #else | ||
| 960 | /* Must reestablish handler each time it is called. */ | ||
| 961 | signal (SIGILL, float_error); | ||
| 962 | #endif /* BSD_SYSTEM */ | ||
| 963 | |||
| 964 | SIGNAL_THREAD_CHECK (signo); | ||
| 965 | in_float = 0; | ||
| 966 | |||
| 967 | xsignal1 (Qarith_error, float_error_arg); | ||
| 968 | } | ||
| 969 | |||
| 970 | /* Another idea was to replace the library function `infnan' | ||
| 971 | where SIGILL is signaled. */ | ||
| 972 | |||
| 973 | #endif /* FLOAT_CATCH_SIGILL */ | ||
| 974 | |||
| 975 | #ifdef HAVE_MATHERR | 943 | #ifdef HAVE_MATHERR |
| 976 | int | 944 | int |
| 977 | matherr (struct exception *x) | 945 | matherr (struct exception *x) |
| @@ -1006,9 +974,6 @@ matherr (struct exception *x) | |||
| 1006 | void | 974 | void |
| 1007 | init_floatfns (void) | 975 | init_floatfns (void) |
| 1008 | { | 976 | { |
| 1009 | #ifdef FLOAT_CATCH_SIGILL | ||
| 1010 | signal (SIGILL, float_error); | ||
| 1011 | #endif | ||
| 1012 | in_float = 0; | 977 | in_float = 0; |
| 1013 | } | 978 | } |
| 1014 | 979 | ||
diff --git a/src/keyboard.c b/src/keyboard.c index fe5372e008c..128f9280911 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -449,9 +449,8 @@ static void restore_getcjmp (jmp_buf); | |||
| 449 | static Lisp_Object apply_modifiers (int, Lisp_Object); | 449 | static Lisp_Object apply_modifiers (int, Lisp_Object); |
| 450 | static void clear_event (struct input_event *); | 450 | static void clear_event (struct input_event *); |
| 451 | static Lisp_Object restore_kboard_configuration (Lisp_Object); | 451 | static Lisp_Object restore_kboard_configuration (Lisp_Object); |
| 452 | static void interrupt_signal (int signalnum); | ||
| 453 | #ifdef SIGIO | 452 | #ifdef SIGIO |
| 454 | static void input_available_signal (int signo); | 453 | static void deliver_input_available_signal (int signo); |
| 455 | #endif | 454 | #endif |
| 456 | static void handle_interrupt (void); | 455 | static void handle_interrupt (void); |
| 457 | static _Noreturn void quit_throw_to_read_char (int); | 456 | static _Noreturn void quit_throw_to_read_char (int); |
| @@ -459,7 +458,7 @@ static void process_special_events (void); | |||
| 459 | static void timer_start_idle (void); | 458 | static void timer_start_idle (void); |
| 460 | static void timer_stop_idle (void); | 459 | static void timer_stop_idle (void); |
| 461 | static void timer_resume_idle (void); | 460 | static void timer_resume_idle (void); |
| 462 | static void handle_user_signal (int); | 461 | static void deliver_user_signal (int); |
| 463 | static char *find_user_signal_name (int); | 462 | static char *find_user_signal_name (int); |
| 464 | static int store_user_signal_events (void); | 463 | static int store_user_signal_events (void); |
| 465 | 464 | ||
| @@ -3833,7 +3832,7 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 3833 | unhold_keyboard_input (); | 3832 | unhold_keyboard_input (); |
| 3834 | #ifdef SIGIO | 3833 | #ifdef SIGIO |
| 3835 | if (!noninteractive) | 3834 | if (!noninteractive) |
| 3836 | signal (SIGIO, input_available_signal); | 3835 | signal (SIGIO, deliver_input_available_signal); |
| 3837 | #endif /* SIGIO */ | 3836 | #endif /* SIGIO */ |
| 3838 | start_polling (); | 3837 | start_polling (); |
| 3839 | } | 3838 | } |
| @@ -7236,12 +7235,8 @@ process_pending_signals (void) | |||
| 7236 | /* Note SIGIO has been undef'd if FIONREAD is missing. */ | 7235 | /* Note SIGIO has been undef'd if FIONREAD is missing. */ |
| 7237 | 7236 | ||
| 7238 | static void | 7237 | static void |
| 7239 | input_available_signal (int signo) | 7238 | handle_input_available_signal (int sig) |
| 7240 | { | 7239 | { |
| 7241 | /* Must preserve main program's value of errno. */ | ||
| 7242 | int old_errno = errno; | ||
| 7243 | SIGNAL_THREAD_CHECK (signo); | ||
| 7244 | |||
| 7245 | #ifdef SYNC_INPUT | 7240 | #ifdef SYNC_INPUT |
| 7246 | interrupt_input_pending = 1; | 7241 | interrupt_input_pending = 1; |
| 7247 | pending_signals = 1; | 7242 | pending_signals = 1; |
| @@ -7253,8 +7248,12 @@ input_available_signal (int signo) | |||
| 7253 | #ifndef SYNC_INPUT | 7248 | #ifndef SYNC_INPUT |
| 7254 | handle_async_input (); | 7249 | handle_async_input (); |
| 7255 | #endif | 7250 | #endif |
| 7251 | } | ||
| 7256 | 7252 | ||
| 7257 | errno = old_errno; | 7253 | static void |
| 7254 | deliver_input_available_signal (int sig) | ||
| 7255 | { | ||
| 7256 | handle_on_main_thread (sig, handle_input_available_signal); | ||
| 7258 | } | 7257 | } |
| 7259 | #endif /* SIGIO */ | 7258 | #endif /* SIGIO */ |
| 7260 | 7259 | ||
| @@ -7310,18 +7309,15 @@ add_user_signal (int sig, const char *name) | |||
| 7310 | p->next = user_signals; | 7309 | p->next = user_signals; |
| 7311 | user_signals = p; | 7310 | user_signals = p; |
| 7312 | 7311 | ||
| 7313 | signal (sig, handle_user_signal); | 7312 | signal (sig, deliver_user_signal); |
| 7314 | } | 7313 | } |
| 7315 | 7314 | ||
| 7316 | static void | 7315 | static void |
| 7317 | handle_user_signal (int sig) | 7316 | handle_user_signal (int sig) |
| 7318 | { | 7317 | { |
| 7319 | int old_errno = errno; | ||
| 7320 | struct user_signal_info *p; | 7318 | struct user_signal_info *p; |
| 7321 | const char *special_event_name = NULL; | 7319 | const char *special_event_name = NULL; |
| 7322 | 7320 | ||
| 7323 | SIGNAL_THREAD_CHECK (sig); | ||
| 7324 | |||
| 7325 | if (SYMBOLP (Vdebug_on_event)) | 7321 | if (SYMBOLP (Vdebug_on_event)) |
| 7326 | special_event_name = SSDATA (SYMBOL_NAME (Vdebug_on_event)); | 7322 | special_event_name = SSDATA (SYMBOL_NAME (Vdebug_on_event)); |
| 7327 | 7323 | ||
| @@ -7355,8 +7351,12 @@ handle_user_signal (int sig) | |||
| 7355 | } | 7351 | } |
| 7356 | break; | 7352 | break; |
| 7357 | } | 7353 | } |
| 7354 | } | ||
| 7358 | 7355 | ||
| 7359 | errno = old_errno; | 7356 | static void |
| 7357 | deliver_user_signal (int sig) | ||
| 7358 | { | ||
| 7359 | handle_on_main_thread (sig, handle_user_signal); | ||
| 7360 | } | 7360 | } |
| 7361 | 7361 | ||
| 7362 | static char * | 7362 | static char * |
| @@ -10776,17 +10776,10 @@ clear_waiting_for_input (void) | |||
| 10776 | Otherwise, tell QUIT to kill Emacs. */ | 10776 | Otherwise, tell QUIT to kill Emacs. */ |
| 10777 | 10777 | ||
| 10778 | static void | 10778 | static void |
| 10779 | interrupt_signal (int signalnum) /* If we don't have an argument, some */ | 10779 | handle_interrupt_signal (int sig) |
| 10780 | /* compilers complain in signal calls. */ | ||
| 10781 | { | 10780 | { |
| 10782 | /* Must preserve main program's value of errno. */ | ||
| 10783 | int old_errno = errno; | ||
| 10784 | struct terminal *terminal; | ||
| 10785 | |||
| 10786 | SIGNAL_THREAD_CHECK (signalnum); | ||
| 10787 | |||
| 10788 | /* See if we have an active terminal on our controlling tty. */ | 10781 | /* See if we have an active terminal on our controlling tty. */ |
| 10789 | terminal = get_named_tty ("/dev/tty"); | 10782 | struct terminal *terminal = get_named_tty ("/dev/tty"); |
| 10790 | if (!terminal) | 10783 | if (!terminal) |
| 10791 | { | 10784 | { |
| 10792 | /* If there are no frames there, let's pretend that we are a | 10785 | /* If there are no frames there, let's pretend that we are a |
| @@ -10807,10 +10800,15 @@ interrupt_signal (int signalnum) /* If we don't have an argument, some */ | |||
| 10807 | 10800 | ||
| 10808 | handle_interrupt (); | 10801 | handle_interrupt (); |
| 10809 | } | 10802 | } |
| 10803 | } | ||
| 10810 | 10804 | ||
| 10811 | errno = old_errno; | 10805 | static void |
| 10806 | deliver_interrupt_signal (int sig) | ||
| 10807 | { | ||
| 10808 | handle_on_main_thread (sig, handle_interrupt_signal); | ||
| 10812 | } | 10809 | } |
| 10813 | 10810 | ||
| 10811 | |||
| 10814 | /* If Emacs is stuck because `inhibit-quit' is true, then keep track | 10812 | /* If Emacs is stuck because `inhibit-quit' is true, then keep track |
| 10815 | of the number of times C-g has been requested. If C-g is pressed | 10813 | of the number of times C-g has been requested. If C-g is pressed |
| 10816 | enough times, then quit anyway. See bug#6585. */ | 10814 | enough times, then quit anyway. See bug#6585. */ |
| @@ -11404,17 +11402,17 @@ init_keyboard (void) | |||
| 11404 | SIGINT. There is special code in interrupt_signal to exit | 11402 | SIGINT. There is special code in interrupt_signal to exit |
| 11405 | Emacs on SIGINT when there are no termcap frames on the | 11403 | Emacs on SIGINT when there are no termcap frames on the |
| 11406 | controlling terminal. */ | 11404 | controlling terminal. */ |
| 11407 | signal (SIGINT, interrupt_signal); | 11405 | signal (SIGINT, deliver_interrupt_signal); |
| 11408 | #ifndef DOS_NT | 11406 | #ifndef DOS_NT |
| 11409 | /* For systems with SysV TERMIO, C-g is set up for both SIGINT and | 11407 | /* For systems with SysV TERMIO, C-g is set up for both SIGINT and |
| 11410 | SIGQUIT and we can't tell which one it will give us. */ | 11408 | SIGQUIT and we can't tell which one it will give us. */ |
| 11411 | signal (SIGQUIT, interrupt_signal); | 11409 | signal (SIGQUIT, deliver_interrupt_signal); |
| 11412 | #endif /* not DOS_NT */ | 11410 | #endif /* not DOS_NT */ |
| 11413 | } | 11411 | } |
| 11414 | /* Note SIGIO has been undef'd if FIONREAD is missing. */ | 11412 | /* Note SIGIO has been undef'd if FIONREAD is missing. */ |
| 11415 | #ifdef SIGIO | 11413 | #ifdef SIGIO |
| 11416 | if (!noninteractive) | 11414 | if (!noninteractive) |
| 11417 | signal (SIGIO, input_available_signal); | 11415 | signal (SIGIO, deliver_input_available_signal); |
| 11418 | #endif /* SIGIO */ | 11416 | #endif /* SIGIO */ |
| 11419 | 11417 | ||
| 11420 | /* Use interrupt input by default, if it works and noninterrupt input | 11418 | /* Use interrupt input by default, if it works and noninterrupt input |
diff --git a/src/lisp.h b/src/lisp.h index bc622ba5212..28e8c1cd1e8 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3256,9 +3256,6 @@ extern bool display_arg; | |||
| 3256 | extern Lisp_Object decode_env_path (const char *, const char *); | 3256 | extern Lisp_Object decode_env_path (const char *, const char *); |
| 3257 | extern Lisp_Object empty_unibyte_string, empty_multibyte_string; | 3257 | extern Lisp_Object empty_unibyte_string, empty_multibyte_string; |
| 3258 | extern Lisp_Object Qfile_name_handler_alist; | 3258 | extern Lisp_Object Qfile_name_handler_alist; |
| 3259 | #ifdef FLOAT_CATCH_SIGILL | ||
| 3260 | extern void fatal_error_signal (int); | ||
| 3261 | #endif | ||
| 3262 | extern _Noreturn void fatal_error_backtrace (int, int); | 3259 | extern _Noreturn void fatal_error_backtrace (int, int); |
| 3263 | extern Lisp_Object Qkill_emacs; | 3260 | extern Lisp_Object Qkill_emacs; |
| 3264 | #if HAVE_SETLOCALE | 3261 | #if HAVE_SETLOCALE |
diff --git a/src/process.c b/src/process.c index 5677da36881..3a6615fb505 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -124,6 +124,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 124 | #include "xgselect.h" | 124 | #include "xgselect.h" |
| 125 | #endif | 125 | #endif |
| 126 | 126 | ||
| 127 | #ifndef WNOHANG | ||
| 128 | # undef waitpid | ||
| 129 | # define waitpid(pid, status, options) wait (status) | ||
| 130 | #endif | ||
| 131 | #ifndef WUNTRACED | ||
| 132 | # define WUNTRACED 0 | ||
| 133 | #endif | ||
| 134 | |||
| 127 | /* Work around GCC 4.7.0 bug with strict overflow checking; see | 135 | /* Work around GCC 4.7.0 bug with strict overflow checking; see |
| 128 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. | 136 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. |
| 129 | These lines can be removed once the GCC bug is fixed. */ | 137 | These lines can be removed once the GCC bug is fixed. */ |
| @@ -801,7 +809,7 @@ get_process (register Lisp_Object name) | |||
| 801 | #ifdef SIGCHLD | 809 | #ifdef SIGCHLD |
| 802 | /* Fdelete_process promises to immediately forget about the process, but in | 810 | /* Fdelete_process promises to immediately forget about the process, but in |
| 803 | reality, Emacs needs to remember those processes until they have been | 811 | reality, Emacs needs to remember those processes until they have been |
| 804 | treated by sigchld_handler; otherwise this handler would consider the | 812 | treated by the SIGCHLD handler; otherwise this handler would consider the |
| 805 | process as being synchronous and say that the synchronous process is | 813 | process as being synchronous and say that the synchronous process is |
| 806 | dead. */ | 814 | dead. */ |
| 807 | static Lisp_Object deleted_pid_list; | 815 | static Lisp_Object deleted_pid_list; |
| @@ -849,7 +857,8 @@ nil, indicating the current buffer's process. */) | |||
| 849 | #endif | 857 | #endif |
| 850 | { | 858 | { |
| 851 | Fkill_process (process, Qnil); | 859 | Fkill_process (process, Qnil); |
| 852 | /* Do this now, since remove_process will make sigchld_handler do nothing. */ | 860 | /* Do this now, since remove_process will make the |
| 861 | SIGCHLD handler do nothing. */ | ||
| 853 | pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil))); | 862 | pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil))); |
| 854 | p->tick = ++process_tick; | 863 | p->tick = ++process_tick; |
| 855 | status_notify (p); | 864 | status_notify (p); |
| @@ -1728,7 +1737,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1728 | if (inchannel > max_process_desc) | 1737 | if (inchannel > max_process_desc) |
| 1729 | max_process_desc = inchannel; | 1738 | max_process_desc = inchannel; |
| 1730 | 1739 | ||
| 1731 | /* Until we store the proper pid, enable sigchld_handler | 1740 | /* Until we store the proper pid, enable the SIGCHLD handler |
| 1732 | to recognize an unknown pid as standing for this process. | 1741 | to recognize an unknown pid as standing for this process. |
| 1733 | It is very important not to let this `marker' value stay | 1742 | It is very important not to let this `marker' value stay |
| 1734 | in the table after this function has returned; if it does | 1743 | in the table after this function has returned; if it does |
| @@ -4956,8 +4965,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4956 | 4965 | ||
| 4957 | if (p->pid == -2) | 4966 | if (p->pid == -2) |
| 4958 | { | 4967 | { |
| 4959 | /* If the EIO occurs on a pty, sigchld_handler's | 4968 | /* If the EIO occurs on a pty, the SIGCHLD handler's |
| 4960 | waitpid() will not find the process object to | 4969 | waitpid call will not find the process object to |
| 4961 | delete. Do it here. */ | 4970 | delete. Do it here. */ |
| 4962 | p->tick = ++process_tick; | 4971 | p->tick = ++process_tick; |
| 4963 | pset_status (p, Qfailed); | 4972 | pset_status (p, Qfailed); |
| @@ -5422,18 +5431,19 @@ read_process_output (Lisp_Object proc, register int channel) | |||
| 5422 | static jmp_buf send_process_frame; | 5431 | static jmp_buf send_process_frame; |
| 5423 | static Lisp_Object process_sent_to; | 5432 | static Lisp_Object process_sent_to; |
| 5424 | 5433 | ||
| 5425 | #ifndef FORWARD_SIGNAL_TO_MAIN_THREAD | 5434 | static _Noreturn void |
| 5426 | static _Noreturn void send_process_trap (int); | 5435 | handle_pipe_signal (int sig) |
| 5427 | #endif | ||
| 5428 | |||
| 5429 | static void | ||
| 5430 | send_process_trap (int ignore) | ||
| 5431 | { | 5436 | { |
| 5432 | SIGNAL_THREAD_CHECK (SIGPIPE); | ||
| 5433 | sigunblock (sigmask (SIGPIPE)); | 5437 | sigunblock (sigmask (SIGPIPE)); |
| 5434 | _longjmp (send_process_frame, 1); | 5438 | _longjmp (send_process_frame, 1); |
| 5435 | } | 5439 | } |
| 5436 | 5440 | ||
| 5441 | static void | ||
| 5442 | deliver_pipe_signal (int sig) | ||
| 5443 | { | ||
| 5444 | handle_on_main_thread (sig, handle_pipe_signal); | ||
| 5445 | } | ||
| 5446 | |||
| 5437 | /* In send_process, when a write fails temporarily, | 5447 | /* In send_process, when a write fails temporarily, |
| 5438 | wait_reading_process_output is called. It may execute user code, | 5448 | wait_reading_process_output is called. It may execute user code, |
| 5439 | e.g. timers, that attempts to write new data to the same process. | 5449 | e.g. timers, that attempts to write new data to the same process. |
| @@ -5663,7 +5673,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5663 | /* Send this batch, using one or more write calls. */ | 5673 | /* Send this batch, using one or more write calls. */ |
| 5664 | ptrdiff_t written = 0; | 5674 | ptrdiff_t written = 0; |
| 5665 | int outfd = p->outfd; | 5675 | int outfd = p->outfd; |
| 5666 | old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap); | 5676 | old_sigpipe = signal (SIGPIPE, deliver_pipe_signal); |
| 5667 | #ifdef DATAGRAM_SOCKETS | 5677 | #ifdef DATAGRAM_SOCKETS |
| 5668 | if (DATAGRAM_CHAN_P (outfd)) | 5678 | if (DATAGRAM_CHAN_P (outfd)) |
| 5669 | { | 5679 | { |
| @@ -6397,143 +6407,135 @@ process has been transmitted to the serial port. */) | |||
| 6397 | indirectly; if it does, that is a bug */ | 6407 | indirectly; if it does, that is a bug */ |
| 6398 | 6408 | ||
| 6399 | #ifdef SIGCHLD | 6409 | #ifdef SIGCHLD |
| 6400 | static void | 6410 | |
| 6401 | sigchld_handler (int signo) | 6411 | /* Record one child's changed status. Return true if a child was found. */ |
| 6412 | static bool | ||
| 6413 | record_child_status_change (void) | ||
| 6402 | { | 6414 | { |
| 6403 | int old_errno = errno; | ||
| 6404 | Lisp_Object proc; | 6415 | Lisp_Object proc; |
| 6405 | struct Lisp_Process *p; | 6416 | struct Lisp_Process *p; |
| 6417 | pid_t pid; | ||
| 6418 | int w; | ||
| 6419 | Lisp_Object tail; | ||
| 6406 | 6420 | ||
| 6407 | SIGNAL_THREAD_CHECK (signo); | 6421 | do |
| 6408 | 6422 | pid = waitpid (-1, &w, WNOHANG | WUNTRACED); | |
| 6409 | while (1) | 6423 | while (pid < 0 && errno == EINTR); |
| 6410 | { | ||
| 6411 | pid_t pid; | ||
| 6412 | int w; | ||
| 6413 | Lisp_Object tail; | ||
| 6414 | |||
| 6415 | #ifdef WNOHANG | ||
| 6416 | #ifndef WUNTRACED | ||
| 6417 | #define WUNTRACED 0 | ||
| 6418 | #endif /* no WUNTRACED */ | ||
| 6419 | /* Keep trying to get a status until we get a definitive result. */ | ||
| 6420 | do | ||
| 6421 | { | ||
| 6422 | errno = 0; | ||
| 6423 | pid = waitpid (-1, &w, WNOHANG | WUNTRACED); | ||
| 6424 | } | ||
| 6425 | while (pid < 0 && errno == EINTR); | ||
| 6426 | |||
| 6427 | if (pid <= 0) | ||
| 6428 | { | ||
| 6429 | /* PID == 0 means no processes found, PID == -1 means a real | ||
| 6430 | failure. We have done all our job, so return. */ | ||
| 6431 | 6424 | ||
| 6432 | errno = old_errno; | 6425 | /* PID == 0 means no processes found, PID == -1 means a real failure. |
| 6433 | return; | 6426 | Either way, we have done all our job. */ |
| 6434 | } | 6427 | if (pid <= 0) |
| 6435 | #else | 6428 | return false; |
| 6436 | pid = wait (&w); | ||
| 6437 | #endif /* no WNOHANG */ | ||
| 6438 | 6429 | ||
| 6439 | /* Find the process that signaled us, and record its status. */ | 6430 | /* Find the process that signaled us, and record its status. */ |
| 6440 | 6431 | ||
| 6441 | /* The process can have been deleted by Fdelete_process. */ | 6432 | /* The process can have been deleted by Fdelete_process. */ |
| 6442 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) | 6433 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) |
| 6434 | { | ||
| 6435 | Lisp_Object xpid = XCAR (tail); | ||
| 6436 | if ((INTEGERP (xpid) && pid == XINT (xpid)) | ||
| 6437 | || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid))) | ||
| 6443 | { | 6438 | { |
| 6444 | Lisp_Object xpid = XCAR (tail); | 6439 | XSETCAR (tail, Qnil); |
| 6445 | if ((INTEGERP (xpid) && pid == XINT (xpid)) | 6440 | return true; |
| 6446 | || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid))) | ||
| 6447 | { | ||
| 6448 | XSETCAR (tail, Qnil); | ||
| 6449 | goto sigchld_end_of_loop; | ||
| 6450 | } | ||
| 6451 | } | 6441 | } |
| 6442 | } | ||
| 6452 | 6443 | ||
| 6453 | /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ | 6444 | /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ |
| 6445 | p = 0; | ||
| 6446 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6447 | { | ||
| 6448 | proc = XCDR (XCAR (tail)); | ||
| 6449 | p = XPROCESS (proc); | ||
| 6450 | if (EQ (p->type, Qreal) && p->pid == pid) | ||
| 6451 | break; | ||
| 6454 | p = 0; | 6452 | p = 0; |
| 6455 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | 6453 | } |
| 6456 | { | ||
| 6457 | proc = XCDR (XCAR (tail)); | ||
| 6458 | p = XPROCESS (proc); | ||
| 6459 | if (EQ (p->type, Qreal) && p->pid == pid) | ||
| 6460 | break; | ||
| 6461 | p = 0; | ||
| 6462 | } | ||
| 6463 | |||
| 6464 | /* Look for an asynchronous process whose pid hasn't been filled | ||
| 6465 | in yet. */ | ||
| 6466 | if (p == 0) | ||
| 6467 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6468 | { | ||
| 6469 | proc = XCDR (XCAR (tail)); | ||
| 6470 | p = XPROCESS (proc); | ||
| 6471 | if (p->pid == -1) | ||
| 6472 | break; | ||
| 6473 | p = 0; | ||
| 6474 | } | ||
| 6475 | |||
| 6476 | /* Change the status of the process that was found. */ | ||
| 6477 | if (p != 0) | ||
| 6478 | { | ||
| 6479 | int clear_desc_flag = 0; | ||
| 6480 | 6454 | ||
| 6481 | p->tick = ++process_tick; | 6455 | /* Look for an asynchronous process whose pid hasn't been filled |
| 6482 | p->raw_status = w; | 6456 | in yet. */ |
| 6483 | p->raw_status_new = 1; | 6457 | if (! p) |
| 6458 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6459 | { | ||
| 6460 | proc = XCDR (XCAR (tail)); | ||
| 6461 | p = XPROCESS (proc); | ||
| 6462 | if (p->pid == -1) | ||
| 6463 | break; | ||
| 6464 | p = 0; | ||
| 6465 | } | ||
| 6484 | 6466 | ||
| 6485 | /* If process has terminated, stop waiting for its output. */ | 6467 | /* Change the status of the process that was found. */ |
| 6486 | if ((WIFSIGNALED (w) || WIFEXITED (w)) | 6468 | if (p) |
| 6487 | && p->infd >= 0) | 6469 | { |
| 6488 | clear_desc_flag = 1; | 6470 | int clear_desc_flag = 0; |
| 6489 | 6471 | ||
| 6490 | /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */ | 6472 | p->tick = ++process_tick; |
| 6491 | if (clear_desc_flag) | 6473 | p->raw_status = w; |
| 6492 | { | 6474 | p->raw_status_new = 1; |
| 6493 | FD_CLR (p->infd, &input_wait_mask); | ||
| 6494 | FD_CLR (p->infd, &non_keyboard_wait_mask); | ||
| 6495 | } | ||
| 6496 | 6475 | ||
| 6497 | /* Tell wait_reading_process_output that it needs to wake up and | 6476 | /* If process has terminated, stop waiting for its output. */ |
| 6498 | look around. */ | 6477 | if ((WIFSIGNALED (w) || WIFEXITED (w)) |
| 6499 | if (input_available_clear_time) | 6478 | && p->infd >= 0) |
| 6500 | *input_available_clear_time = make_emacs_time (0, 0); | 6479 | clear_desc_flag = 1; |
| 6501 | } | ||
| 6502 | 6480 | ||
| 6503 | /* There was no asynchronous process found for that pid: we have | 6481 | /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */ |
| 6504 | a synchronous process. */ | 6482 | if (clear_desc_flag) |
| 6505 | else | ||
| 6506 | { | 6483 | { |
| 6507 | synch_process_alive = 0; | 6484 | FD_CLR (p->infd, &input_wait_mask); |
| 6508 | 6485 | FD_CLR (p->infd, &non_keyboard_wait_mask); | |
| 6509 | /* Report the status of the synchronous process. */ | ||
| 6510 | if (WIFEXITED (w)) | ||
| 6511 | synch_process_retcode = WEXITSTATUS (w); | ||
| 6512 | else if (WIFSIGNALED (w)) | ||
| 6513 | synch_process_termsig = WTERMSIG (w); | ||
| 6514 | |||
| 6515 | /* Tell wait_reading_process_output that it needs to wake up and | ||
| 6516 | look around. */ | ||
| 6517 | if (input_available_clear_time) | ||
| 6518 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6519 | } | 6486 | } |
| 6520 | 6487 | ||
| 6521 | sigchld_end_of_loop: | 6488 | /* Tell wait_reading_process_output that it needs to wake up and |
| 6522 | ; | 6489 | look around. */ |
| 6490 | if (input_available_clear_time) | ||
| 6491 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6492 | } | ||
| 6493 | /* There was no asynchronous process found for that pid: we have | ||
| 6494 | a synchronous process. */ | ||
| 6495 | else | ||
| 6496 | { | ||
| 6497 | synch_process_alive = 0; | ||
| 6498 | |||
| 6499 | /* Report the status of the synchronous process. */ | ||
| 6500 | if (WIFEXITED (w)) | ||
| 6501 | synch_process_retcode = WEXITSTATUS (w); | ||
| 6502 | else if (WIFSIGNALED (w)) | ||
| 6503 | synch_process_termsig = WTERMSIG (w); | ||
| 6504 | |||
| 6505 | /* Tell wait_reading_process_output that it needs to wake up and | ||
| 6506 | look around. */ | ||
| 6507 | if (input_available_clear_time) | ||
| 6508 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6509 | } | ||
| 6510 | |||
| 6511 | return true; | ||
| 6512 | } | ||
| 6523 | 6513 | ||
| 6524 | /* On some systems, we must return right away. | 6514 | /* On some systems, the SIGCHLD handler must return right away. If |
| 6525 | If any more processes want to signal us, we will | 6515 | any more processes want to signal us, we will get another signal. |
| 6526 | get another signal. | 6516 | Otherwise, loop around to use up all the processes that have |
| 6527 | Otherwise (on systems that have WNOHANG), loop around | 6517 | something to tell us. */ |
| 6528 | to use up all the processes that have something to tell us. */ | ||
| 6529 | #if (defined WINDOWSNT \ | 6518 | #if (defined WINDOWSNT \ |
| 6530 | || (defined USG && !defined GNU_LINUX \ | 6519 | || (defined USG && !defined GNU_LINUX \ |
| 6531 | && !(defined HPUX && defined WNOHANG))) | 6520 | && !(defined HPUX && defined WNOHANG))) |
| 6532 | errno = old_errno; | 6521 | enum { CAN_HANDLE_MULTIPLE_CHILDREN = 1 }; |
| 6533 | return; | 6522 | #else |
| 6534 | #endif /* USG, but not HPUX with WNOHANG */ | 6523 | enum { CAN_HANDLE_MULTIPLE_CHILDREN = 0 }; |
| 6535 | } | 6524 | #endif |
| 6525 | |||
| 6526 | static void | ||
| 6527 | handle_child_signal (int sig) | ||
| 6528 | { | ||
| 6529 | while (record_child_status_change () && CAN_HANDLE_MULTIPLE_CHILDREN) | ||
| 6530 | continue; | ||
| 6536 | } | 6531 | } |
| 6532 | |||
| 6533 | static void | ||
| 6534 | deliver_child_signal (int sig) | ||
| 6535 | { | ||
| 6536 | handle_on_main_thread (sig, handle_child_signal); | ||
| 6537 | } | ||
| 6538 | |||
| 6537 | #endif /* SIGCHLD */ | 6539 | #endif /* SIGCHLD */ |
| 6538 | 6540 | ||
| 6539 | 6541 | ||
| @@ -7387,7 +7389,7 @@ init_process_emacs (void) | |||
| 7387 | #ifndef CANNOT_DUMP | 7389 | #ifndef CANNOT_DUMP |
| 7388 | if (! noninteractive || initialized) | 7390 | if (! noninteractive || initialized) |
| 7389 | #endif | 7391 | #endif |
| 7390 | signal (SIGCHLD, sigchld_handler); | 7392 | signal (SIGCHLD, deliver_child_signal); |
| 7391 | #endif | 7393 | #endif |
| 7392 | 7394 | ||
| 7393 | FD_ZERO (&input_wait_mask); | 7395 | FD_ZERO (&input_wait_mask); |
diff --git a/src/sysdep.c b/src/sysdep.c index 1f4de194c64..42b8baf78e0 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -1551,6 +1551,40 @@ sys_sigsetmask (sigset_t new_mask) | |||
| 1551 | return (old_mask); | 1551 | return (old_mask); |
| 1552 | } | 1552 | } |
| 1553 | 1553 | ||
| 1554 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD | ||
| 1555 | pthread_t main_thread; | ||
| 1556 | #endif | ||
| 1557 | |||
| 1558 | /* If we are on the main thread, handle the signal SIG with HANDLER. | ||
| 1559 | Otherwise, redirect the signal to the main thread, blocking it from | ||
| 1560 | this thread. POSIX says any thread can receive a signal that is | ||
| 1561 | associated with a process, process group, or asynchronous event. | ||
| 1562 | On GNU/Linux that is not true, but for other systems (FreeBSD at | ||
| 1563 | least) it is. */ | ||
| 1564 | void | ||
| 1565 | handle_on_main_thread (int sig, signal_handler_t handler) | ||
| 1566 | { | ||
| 1567 | /* Preserve errno, to avoid race conditions with signal handlers that | ||
| 1568 | might change errno. Races can occur even in single-threaded hosts. */ | ||
| 1569 | int old_errno = errno; | ||
| 1570 | |||
| 1571 | bool on_main_thread = true; | ||
| 1572 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD | ||
| 1573 | if (! pthread_equal (pthread_self (), main_thread)) | ||
| 1574 | { | ||
| 1575 | sigset_t blocked; | ||
| 1576 | sigemptyset (&blocked); | ||
| 1577 | sigaddset (&blocked, sig); | ||
| 1578 | pthread_sigmask (SIG_BLOCK, &blocked, 0); | ||
| 1579 | pthread_kill (main_thread, sig); | ||
| 1580 | on_main_thread = false; | ||
| 1581 | } | ||
| 1582 | #endif | ||
| 1583 | if (on_main_thread) | ||
| 1584 | handler (sig); | ||
| 1585 | |||
| 1586 | errno = old_errno; | ||
| 1587 | } | ||
| 1554 | 1588 | ||
| 1555 | #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST | 1589 | #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST |
| 1556 | static char *my_sys_siglist[NSIG]; | 1590 | static char *my_sys_siglist[NSIG]; |
| @@ -1565,6 +1599,10 @@ init_signals (void) | |||
| 1565 | { | 1599 | { |
| 1566 | sigemptyset (&empty_mask); | 1600 | sigemptyset (&empty_mask); |
| 1567 | 1601 | ||
| 1602 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD | ||
| 1603 | main_thread = pthread_self (); | ||
| 1604 | #endif | ||
| 1605 | |||
| 1568 | #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST | 1606 | #if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST |
| 1569 | if (! initialized) | 1607 | if (! initialized) |
| 1570 | { | 1608 | { |
diff --git a/src/syssignal.h b/src/syssignal.h index 71151ed4c6a..504aff43083 100644 --- a/src/syssignal.h +++ b/src/syssignal.h | |||
| @@ -133,24 +133,5 @@ char *strsignal (int); | |||
| 133 | 133 | ||
| 134 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD | 134 | #ifdef FORWARD_SIGNAL_TO_MAIN_THREAD |
| 135 | extern pthread_t main_thread; | 135 | extern pthread_t main_thread; |
| 136 | #define SIGNAL_THREAD_CHECK(signo) \ | 136 | void handle_on_main_thread (int, signal_handler_t); |
| 137 | do { \ | 137 | #endif |
| 138 | if (!pthread_equal (pthread_self (), main_thread)) \ | ||
| 139 | { \ | ||
| 140 | /* POSIX says any thread can receive the signal. On GNU/Linux \ | ||
| 141 | that is not true, but for other systems (FreeBSD at least) \ | ||
| 142 | it is. So direct the signal to the correct thread and block \ | ||
| 143 | it from this thread. */ \ | ||
| 144 | sigset_t new_mask; \ | ||
| 145 | \ | ||
| 146 | sigemptyset (&new_mask); \ | ||
| 147 | sigaddset (&new_mask, signo); \ | ||
| 148 | pthread_sigmask (SIG_BLOCK, &new_mask, 0); \ | ||
| 149 | pthread_kill (main_thread, signo); \ | ||
| 150 | return; \ | ||
| 151 | } \ | ||
| 152 | } while (0) | ||
| 153 | |||
| 154 | #else /* not FORWARD_SIGNAL_TO_MAIN_THREAD */ | ||
| 155 | #define SIGNAL_THREAD_CHECK(signo) | ||
| 156 | #endif /* not FORWARD_SIGNAL_TO_MAIN_THREAD */ | ||