]> git.eshelyaron.com Git - emacs.git/commitdiff
Avoid crashes in batch Emacs sub-processes on MS-Windows
authorEli Zaretskii <eliz@gnu.org>
Sun, 22 Jan 2023 13:07:55 +0000 (15:07 +0200)
committerEli Zaretskii <eliz@gnu.org>
Sun, 22 Jan 2023 13:09:21 +0000 (15:09 +0200)
* 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)

src/w32.c
src/w32fns.c

index 47d79abc5b0e61336e8ae403f30664e12d94f542..213fee15699f39cc81ebbb3cd41e274b8754e157 100644 (file)
--- 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.  */
index b4192a5ffa65ec87c4803c5ebb230f9e592b3419..745f561e6b1b3e778099a5e1b82d88d60e02a7be 100644 (file)
@@ -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: