diff options
| author | Eli Zaretskii | 2012-09-25 13:50:01 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2012-09-25 13:50:01 +0200 |
| commit | 16b22fef423afedf034460a0f811abf50d0c5f3e (patch) | |
| tree | 42d6127bd2c77a3e8cb34c90276d3c23ca3224d4 /src | |
| parent | 9c52dd5a2ef4457d3a4bc33720ca5eb766d939a5 (diff) | |
| download | emacs-16b22fef423afedf034460a0f811abf50d0c5f3e.tar.gz emacs-16b22fef423afedf034460a0f811abf50d0c5f3e.zip | |
Fix handling of fatal signals and exceptions on MS-Windows.
src/w32proc.c (sys_signal): Handle all signals defined by the
MS-Windows runtime, not just SIGCHLD. Actually install the signal
handlers for signals supported by Windows. Don't override
term_ntproc as the handler for SIGABRT.
(sigaction): Rewrite to call sys_signal instead of duplicating its
code.
(sys_kill): Improve commentary.
src/w32.c (term_ntproc): Accept (and ignore) one argument, for
consistency with a signature of a signal handler. All callers
changed.
(init_ntproc): Accept an argument DUMPING. If dumping, don't
install term_ntproc as a signal handler for SIGABRT, as that
should be done by the dumped Emacs.
src/w32.h (init_ntproc, term_ntproc): Adjust prototypes.
src/w32select.c (term_w32select): Protect against repeated
invocation by setting clipboard_owner to NULL after calling
DestroyWindow.
src/emacs.c (shut_down_emacs, main): Adapt the calls to init_ntproc
and term_ntproc to their modified signatures.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 24 | ||||
| -rw-r--r-- | src/emacs.c | 4 | ||||
| -rw-r--r-- | src/w32.c | 8 | ||||
| -rw-r--r-- | src/w32.h | 4 | ||||
| -rw-r--r-- | src/w32proc.c | 44 | ||||
| -rw-r--r-- | src/w32select.c | 5 |
6 files changed, 71 insertions, 18 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index ca9ca808c77..9d048beeec1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,29 @@ | |||
| 1 | 2012-09-25 Eli Zaretskii <eliz@gnu.org> | 1 | 2012-09-25 Eli Zaretskii <eliz@gnu.org> |
| 2 | 2 | ||
| 3 | * w32proc.c (sys_signal): Handle all signals defined by the | ||
| 4 | MS-Windows runtime, not just SIGCHLD. Actually install the signal | ||
| 5 | handlers for signals supported by Windows. Don't override | ||
| 6 | term_ntproc as the handler for SIGABRT. | ||
| 7 | (sigaction): Rewrite to call sys_signal instead of duplicating its | ||
| 8 | code. | ||
| 9 | (sys_kill): Improve commentary. | ||
| 10 | |||
| 11 | * w32.c (term_ntproc): Accept (and ignore) one argument, for | ||
| 12 | consistency with a signature of a signal handler. All callers | ||
| 13 | changed. | ||
| 14 | (init_ntproc): Accept an argument DUMPING. If dumping, don't | ||
| 15 | install term_ntproc as a signal handler for SIGABRT, as that | ||
| 16 | should be done by the dumped Emacs. | ||
| 17 | |||
| 18 | * w32.h (init_ntproc, term_ntproc): Adjust prototypes. | ||
| 19 | |||
| 20 | * w32select.c (term_w32select): Protect against repeated | ||
| 21 | invocation by setting clipboard_owner to NULL after calling | ||
| 22 | DestroyWindow. | ||
| 23 | |||
| 24 | * emacs.c (shut_down_emacs, main): Adapt the calls to init_ntproc | ||
| 25 | and term_ntproc to their modified signatures. | ||
| 26 | |||
| 3 | * character.c (char_string, string_char): Remove calls to | 27 | * character.c (char_string, string_char): Remove calls to |
| 4 | MAYBE_UNIFY_CHAR. See the discussion starting at | 28 | MAYBE_UNIFY_CHAR. See the discussion starting at |
| 5 | http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00433.html | 29 | http://lists.gnu.org/archive/html/emacs-devel/2012-09/msg00433.html |
diff --git a/src/emacs.c b/src/emacs.c index cf3d50b4f86..686a884cdbb 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1258,7 +1258,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1258 | globals_of_w32 (); | 1258 | globals_of_w32 (); |
| 1259 | /* Initialize environment from registry settings. */ | 1259 | /* Initialize environment from registry settings. */ |
| 1260 | init_environment (argv); | 1260 | init_environment (argv); |
| 1261 | init_ntproc (); /* must precede init_editfns. */ | 1261 | init_ntproc (dumping); /* must precede init_editfns. */ |
| 1262 | #endif | 1262 | #endif |
| 1263 | 1263 | ||
| 1264 | /* Initialize and GC-protect Vinitial_environment and | 1264 | /* Initialize and GC-protect Vinitial_environment and |
| @@ -1906,7 +1906,7 @@ shut_down_emacs (int sig, Lisp_Object stuff) | |||
| 1906 | ignore_sigio (); | 1906 | ignore_sigio (); |
| 1907 | 1907 | ||
| 1908 | #ifdef WINDOWSNT | 1908 | #ifdef WINDOWSNT |
| 1909 | term_ntproc (); | 1909 | term_ntproc (0); |
| 1910 | #endif | 1910 | #endif |
| 1911 | 1911 | ||
| 1912 | /* Do this only if terminating normally, we want glyph matrices | 1912 | /* Do this only if terminating normally, we want glyph matrices |
| @@ -6624,8 +6624,9 @@ check_windows_init_file (void) | |||
| 6624 | } | 6624 | } |
| 6625 | 6625 | ||
| 6626 | void | 6626 | void |
| 6627 | term_ntproc (void) | 6627 | term_ntproc (int ignored) |
| 6628 | { | 6628 | { |
| 6629 | (void)ignored; | ||
| 6629 | /* shutdown the socket interface if necessary */ | 6630 | /* shutdown the socket interface if necessary */ |
| 6630 | term_winsock (); | 6631 | term_winsock (); |
| 6631 | 6632 | ||
| @@ -6633,7 +6634,7 @@ term_ntproc (void) | |||
| 6633 | } | 6634 | } |
| 6634 | 6635 | ||
| 6635 | void | 6636 | void |
| 6636 | init_ntproc (void) | 6637 | init_ntproc (int dumping) |
| 6637 | { | 6638 | { |
| 6638 | /* Initialize the socket interface now if available and requested by | 6639 | /* Initialize the socket interface now if available and requested by |
| 6639 | the user by defining PRELOAD_WINSOCK; otherwise loading will be | 6640 | the user by defining PRELOAD_WINSOCK; otherwise loading will be |
| @@ -6710,7 +6711,8 @@ init_ntproc (void) | |||
| 6710 | 6711 | ||
| 6711 | /* unfortunately, atexit depends on implementation of malloc */ | 6712 | /* unfortunately, atexit depends on implementation of malloc */ |
| 6712 | /* atexit (term_ntproc); */ | 6713 | /* atexit (term_ntproc); */ |
| 6713 | signal (SIGABRT, term_ntproc); | 6714 | if (!dumping) |
| 6715 | signal (SIGABRT, term_ntproc); | ||
| 6714 | 6716 | ||
| 6715 | /* determine which drives are fixed, for GetCachedVolumeInformation */ | 6717 | /* determine which drives are fixed, for GetCachedVolumeInformation */ |
| 6716 | { | 6718 | { |
| @@ -127,8 +127,8 @@ extern void reset_standard_handles (int in, int out, | |||
| 127 | /* Return the string resource associated with KEY of type TYPE. */ | 127 | /* Return the string resource associated with KEY of type TYPE. */ |
| 128 | extern LPBYTE w32_get_resource (char * key, LPDWORD type); | 128 | extern LPBYTE w32_get_resource (char * key, LPDWORD type); |
| 129 | 129 | ||
| 130 | extern void init_ntproc (void); | 130 | extern void init_ntproc (int); |
| 131 | extern void term_ntproc (void); | 131 | extern void term_ntproc (int); |
| 132 | extern void globals_of_w32 (void); | 132 | extern void globals_of_w32 (void); |
| 133 | extern void syms_of_w32term (void); | 133 | extern void syms_of_w32term (void); |
| 134 | extern void syms_of_w32fns (void); | 134 | extern void syms_of_w32fns (void); |
diff --git a/src/w32proc.c b/src/w32proc.c index 8dbd063a96b..b367b42d8c6 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -86,19 +86,34 @@ typedef void (_CALLBACK_ *signal_handler) (int); | |||
| 86 | /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */ | 86 | /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */ |
| 87 | static signal_handler sig_handlers[NSIG]; | 87 | static signal_handler sig_handlers[NSIG]; |
| 88 | 88 | ||
| 89 | /* Fake signal implementation to record the SIGCHLD handler. */ | 89 | /* Improve on the CRT 'signal' implementation so that we could record |
| 90 | the SIGCHLD handler. */ | ||
| 90 | signal_handler | 91 | signal_handler |
| 91 | sys_signal (int sig, signal_handler handler) | 92 | sys_signal (int sig, signal_handler handler) |
| 92 | { | 93 | { |
| 93 | signal_handler old; | 94 | signal_handler old; |
| 94 | 95 | ||
| 95 | if (sig != SIGCHLD) | 96 | /* SIGCHLD is needed for supporting subprocesses, see sys_kill |
| 97 | below. All the others are the only ones supported by the MS | ||
| 98 | runtime. */ | ||
| 99 | if (!(sig == SIGCHLD || sig == SIGSEGV || sig == SIGILL | ||
| 100 | || sig == SIGFPE || sig == SIGABRT || sig == SIGTERM)) | ||
| 96 | { | 101 | { |
| 97 | errno = EINVAL; | 102 | errno = EINVAL; |
| 98 | return SIG_ERR; | 103 | return SIG_ERR; |
| 99 | } | 104 | } |
| 100 | old = sig_handlers[sig]; | 105 | old = sig_handlers[sig]; |
| 101 | sig_handlers[sig] = handler; | 106 | /* SIGABRT is treated specially because w32.c installs term_ntproc |
| 107 | as its handler, so we don't want to override that afterwards. | ||
| 108 | Aborting Emacs works specially anyway: either by calling | ||
| 109 | emacs_abort directly or through terminate_due_to_signal, which | ||
| 110 | calls emacs_abort through emacs_raise. */ | ||
| 111 | if (!(sig == SIGABRT && old == term_ntproc)) | ||
| 112 | { | ||
| 113 | sig_handlers[sig] = handler; | ||
| 114 | if (sig != SIGCHLD) | ||
| 115 | signal (sig, handler); | ||
| 116 | } | ||
| 102 | return old; | 117 | return old; |
| 103 | } | 118 | } |
| 104 | 119 | ||
| @@ -106,23 +121,26 @@ sys_signal (int sig, signal_handler handler) | |||
| 106 | int | 121 | int |
| 107 | sigaction (int sig, const struct sigaction *act, struct sigaction *oact) | 122 | sigaction (int sig, const struct sigaction *act, struct sigaction *oact) |
| 108 | { | 123 | { |
| 109 | signal_handler old; | 124 | signal_handler old = SIG_DFL; |
| 125 | int retval = 0; | ||
| 126 | |||
| 127 | if (act) | ||
| 128 | old = sys_signal (sig, act->sa_handler); | ||
| 129 | else if (oact) | ||
| 130 | old = sig_handlers[sig]; | ||
| 110 | 131 | ||
| 111 | if (sig != SIGCHLD) | 132 | if (old == SIG_ERR) |
| 112 | { | 133 | { |
| 113 | errno = EINVAL; | 134 | errno = EINVAL; |
| 114 | return -1; | 135 | retval = -1; |
| 115 | } | 136 | } |
| 116 | old = sig_handlers[sig]; | ||
| 117 | if (act) | ||
| 118 | sig_handlers[sig] = act->sa_handler; | ||
| 119 | if (oact) | 137 | if (oact) |
| 120 | { | 138 | { |
| 121 | oact->sa_handler = old; | 139 | oact->sa_handler = old; |
| 122 | oact->sa_flags = 0; | 140 | oact->sa_flags = 0; |
| 123 | oact->sa_mask = empty_mask; | 141 | oact->sa_mask = empty_mask; |
| 124 | } | 142 | } |
| 125 | return 0; | 143 | return retval; |
| 126 | } | 144 | } |
| 127 | 145 | ||
| 128 | /* Defined in <process.h> which conflicts with the local copy */ | 146 | /* Defined in <process.h> which conflicts with the local copy */ |
| @@ -1420,6 +1438,7 @@ find_child_console (HWND hwnd, LPARAM arg) | |||
| 1420 | return TRUE; | 1438 | return TRUE; |
| 1421 | } | 1439 | } |
| 1422 | 1440 | ||
| 1441 | /* Emulate 'kill', but only for other processes. */ | ||
| 1423 | int | 1442 | int |
| 1424 | sys_kill (int pid, int sig) | 1443 | sys_kill (int pid, int sig) |
| 1425 | { | 1444 | { |
| @@ -1438,6 +1457,11 @@ sys_kill (int pid, int sig) | |||
| 1438 | cp = find_child_pid (pid); | 1457 | cp = find_child_pid (pid); |
| 1439 | if (cp == NULL) | 1458 | if (cp == NULL) |
| 1440 | { | 1459 | { |
| 1460 | /* We were passed a PID of something other than our subprocess. | ||
| 1461 | If that is our own PID, we will send to ourself a message to | ||
| 1462 | close the selected frame, which does not necessarily | ||
| 1463 | terminates Emacs. But then we are not supposed to call | ||
| 1464 | sys_kill with our own PID. */ | ||
| 1441 | proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid); | 1465 | proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid); |
| 1442 | if (proc_hand == NULL) | 1466 | if (proc_hand == NULL) |
| 1443 | { | 1467 | { |
diff --git a/src/w32select.c b/src/w32select.c index 061f5a4a0a8..66f9f7ab041 100644 --- a/src/w32select.c +++ b/src/w32select.c | |||
| @@ -474,7 +474,10 @@ term_w32select (void) | |||
| 474 | { | 474 | { |
| 475 | /* This is needed to trigger WM_RENDERALLFORMATS. */ | 475 | /* This is needed to trigger WM_RENDERALLFORMATS. */ |
| 476 | if (clipboard_owner != NULL) | 476 | if (clipboard_owner != NULL) |
| 477 | DestroyWindow (clipboard_owner); | 477 | { |
| 478 | DestroyWindow (clipboard_owner); | ||
| 479 | clipboard_owner = NULL; | ||
| 480 | } | ||
| 478 | } | 481 | } |
| 479 | 482 | ||
| 480 | static void | 483 | static void |