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)
This commit is contained in:
Eli Zaretskii 2023-01-22 15:07:55 +02:00
parent 808e101fab
commit 8e83604dfe
2 changed files with 47 additions and 25 deletions

View file

@ -10509,10 +10509,13 @@ init_ntproc (int dumping)
} }
} }
/* /* shutdown_handler ensures that buffers' autosave files are up to
shutdown_handler ensures that buffers' autosave files are date when the user logs off, or the system shuts down. It also
up to date when the user logs off, or the system shuts down. 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 static BOOL WINAPI
shutdown_handler (DWORD type) shutdown_handler (DWORD type)
{ {
@ -10520,6 +10523,8 @@ shutdown_handler (DWORD type)
if (type == CTRL_CLOSE_EVENT /* User closes console window. */ if (type == CTRL_CLOSE_EVENT /* User closes console window. */
|| type == CTRL_LOGOFF_EVENT /* User logs off. */ || type == CTRL_LOGOFF_EVENT /* User logs off. */
|| type == CTRL_SHUTDOWN_EVENT) /* User shutsdown. */ || type == CTRL_SHUTDOWN_EVENT) /* User shutsdown. */
{
if (GetCurrentThreadId () == dwMainThreadId)
{ {
/* If we are being shut down in noninteractive mode, we don't /* If we are being shut down in noninteractive mode, we don't
care about the message stack, so clear it to avoid abort in care about the message stack, so clear it to avoid abort in
@ -10531,6 +10536,19 @@ shutdown_handler (DWORD type)
/* Shut down cleanly, making sure autosave files are up to date. */ /* Shut down cleanly, making sure autosave files are up to date. */
shut_down_emacs (0, Qnil); 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. */ /* Allow other handlers to handle this signal. */
return FALSE; return FALSE;

View file

@ -11112,6 +11112,10 @@ emacs_abort (void)
abort (); abort ();
int button; int button;
if (noninteractive)
button = IDNO;
else
button = MessageBox (NULL, button = MessageBox (NULL,
"A fatal error has occurred!\n\n" "A fatal error has occurred!\n\n"
"Would you like to attach a debugger?\n\n" "Would you like to attach a debugger?\n\n"
@ -11120,8 +11124,8 @@ emacs_abort (void)
"NO -- to abort Emacs and produce a backtrace\n" "NO -- to abort Emacs and produce a backtrace\n"
" (emacs_backtrace.txt in current directory)." " (emacs_backtrace.txt in current directory)."
#if __GNUC__ #if __GNUC__
"\n\n(type \"gdb -p <emacs-PID>\" and\n" "\n\n(Before clicking YES, type\n"
"\"continue\" inside GDB before clicking YES.)" "\"gdb -p <emacs-PID>\", then \"continue\" inside GDB.)"
#endif #endif
, "Emacs Abort Dialog", , "Emacs Abort Dialog",
MB_ICONEXCLAMATION | MB_TASKMODAL MB_ICONEXCLAMATION | MB_TASKMODAL