summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2023-01-22 15:07:55 +0200
committerEli Zaretskii <eliz@gnu.org>2023-01-22 15:09:21 +0200
commit8e83604dfe01e0ea56569c1bc129ecbc67583447 (patch)
tree3dab806ad5ea0adc8fbb6709281c76486318464a
parent808e101fabec64a2f7a42dd9d9207ebd402ead4f (diff)
downloademacs-8e83604dfe01e0ea56569c1bc129ecbc67583447.tar.gz
Avoid crashes in batch Emacs sub-processes on MS-Windows
* src/w32.c (shutdown_handler): When run in a separate thread, don't call functions that only the main (a.k.a. "Lisp") thread can call; instead, arrange for maybe_quit to kill Emacs. * src/w32fns.c (emacs_abort): Don't show GUI Abort dialogs in non-interactive sessions. (Bug#60556)
-rw-r--r--src/w32.c44
-rw-r--r--src/w32fns.c28
2 files changed, 47 insertions, 25 deletions
diff --git a/src/w32.c b/src/w32.c
index 47d79abc5b0..213fee15699 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -10509,10 +10509,13 @@ init_ntproc (int dumping)
}
}
-/*
- shutdown_handler ensures that buffers' autosave files are
- up to date when the user logs off, or the system shuts down.
-*/
+/* shutdown_handler ensures that buffers' autosave files are up to
+ date when the user logs off, or the system shuts down. It also
+ shuts down Emacs when we get killed by another Emacs process, in
+ which case we get the CTRL_CLOSE_EVENT. */
+
+extern DWORD dwMainThreadId;
+
static BOOL WINAPI
shutdown_handler (DWORD type)
{
@@ -10521,15 +10524,30 @@ shutdown_handler (DWORD type)
|| type == CTRL_LOGOFF_EVENT /* User logs off. */
|| type == CTRL_SHUTDOWN_EVENT) /* User shutsdown. */
{
- /* If we are being shut down in noninteractive mode, we don't
- care about the message stack, so clear it to avoid abort in
- shut_down_emacs. This happens when an noninteractive Emacs
- is invoked as a subprocess of Emacs, and the parent wants to
- kill us, e.g. because it's about to exit. */
- if (noninteractive)
- clear_message_stack ();
- /* Shut down cleanly, making sure autosave files are up to date. */
- shut_down_emacs (0, Qnil);
+ if (GetCurrentThreadId () == dwMainThreadId)
+ {
+ /* If we are being shut down in noninteractive mode, we don't
+ care about the message stack, so clear it to avoid abort in
+ shut_down_emacs. This happens when an noninteractive Emacs
+ is invoked as a subprocess of Emacs, and the parent wants to
+ kill us, e.g. because it's about to exit. */
+ if (noninteractive)
+ clear_message_stack ();
+ /* Shut down cleanly, making sure autosave files are up to date. */
+ shut_down_emacs (0, Qnil);
+ }
+ {
+ /* This handler is run in a thread different from the main
+ thread. (This is the normal situation when we are killed
+ by Emacs, for example, which sends us the WM_CLOSE
+ message). We cannot possibly call functions like
+ shut_down_emacs or clear_message_stack in that case, since
+ the main (a.k.a. "Lisp") thread could be in the middle of
+ some Lisp program. So instead we arrange for maybe_quit to
+ kill Emacs. */
+ Vquit_flag = Qkill_emacs;
+ Vinhibit_quit = Qnil;
+ }
}
/* Allow other handlers to handle this signal. */
diff --git a/src/w32fns.c b/src/w32fns.c
index b4192a5ffa6..745f561e6b1 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -11112,20 +11112,24 @@ emacs_abort (void)
abort ();
int button;
- button = MessageBox (NULL,
- "A fatal error has occurred!\n\n"
- "Would you like to attach a debugger?\n\n"
- "Select:\n"
- "YES -- to debug Emacs, or\n"
- "NO -- to abort Emacs and produce a backtrace\n"
- " (emacs_backtrace.txt in current directory)."
+
+ if (noninteractive)
+ button = IDNO;
+ else
+ button = MessageBox (NULL,
+ "A fatal error has occurred!\n\n"
+ "Would you like to attach a debugger?\n\n"
+ "Select:\n"
+ "YES -- to debug Emacs, or\n"
+ "NO -- to abort Emacs and produce a backtrace\n"
+ " (emacs_backtrace.txt in current directory)."
#if __GNUC__
- "\n\n(type \"gdb -p <emacs-PID>\" and\n"
- "\"continue\" inside GDB before clicking YES.)"
+ "\n\n(Before clicking YES, type\n"
+ "\"gdb -p <emacs-PID>\", then \"continue\" inside GDB.)"
#endif
- , "Emacs Abort Dialog",
- MB_ICONEXCLAMATION | MB_TASKMODAL
- | MB_SETFOREGROUND | MB_YESNO);
+ , "Emacs Abort Dialog",
+ MB_ICONEXCLAMATION | MB_TASKMODAL
+ | MB_SETFOREGROUND | MB_YESNO);
switch (button)
{
case IDYES: