aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2012-09-25 13:50:01 +0200
committerEli Zaretskii2012-09-25 13:50:01 +0200
commit16b22fef423afedf034460a0f811abf50d0c5f3e (patch)
tree42d6127bd2c77a3e8cb34c90276d3c23ca3224d4 /src
parent9c52dd5a2ef4457d3a4bc33720ca5eb766d939a5 (diff)
downloademacs-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/ChangeLog24
-rw-r--r--src/emacs.c4
-rw-r--r--src/w32.c8
-rw-r--r--src/w32.h4
-rw-r--r--src/w32proc.c44
-rw-r--r--src/w32select.c5
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 @@
12012-09-25 Eli Zaretskii <eliz@gnu.org> 12012-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
diff --git a/src/w32.c b/src/w32.c
index 8775a366e61..f7e16354791 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -6624,8 +6624,9 @@ check_windows_init_file (void)
6624} 6624}
6625 6625
6626void 6626void
6627term_ntproc (void) 6627term_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
6635void 6636void
6636init_ntproc (void) 6637init_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 {
diff --git a/src/w32.h b/src/w32.h
index 39409e38082..18625cea955 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -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. */
128extern LPBYTE w32_get_resource (char * key, LPDWORD type); 128extern LPBYTE w32_get_resource (char * key, LPDWORD type);
129 129
130extern void init_ntproc (void); 130extern void init_ntproc (int);
131extern void term_ntproc (void); 131extern void term_ntproc (int);
132extern void globals_of_w32 (void); 132extern void globals_of_w32 (void);
133extern void syms_of_w32term (void); 133extern void syms_of_w32term (void);
134extern void syms_of_w32fns (void); 134extern 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. */
87static signal_handler sig_handlers[NSIG]; 87static 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. */
90signal_handler 91signal_handler
91sys_signal (int sig, signal_handler handler) 92sys_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)
106int 121int
107sigaction (int sig, const struct sigaction *act, struct sigaction *oact) 122sigaction (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. */
1423int 1442int
1424sys_kill (int pid, int sig) 1443sys_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
480static void 483static void