]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix 'restart-emacs' on MS-Windows
authorEli Zaretskii <eliz@gnu.org>
Sun, 17 Apr 2022 14:20:03 +0000 (17:20 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sun, 17 Apr 2022 14:20:03 +0000 (17:20 +0300)
* src/w32.c (w32_reexec_emacs): New function, emulation of
'execvp' on Posix systems.
* src/w32.h (w32_reexec_emacs): Add prototype.
* src/emacs.c (main) [WINDOWSNT]: Save the original command line
and working directory.
(Fkill_emacs) [WINDOWSNT]: Call 'w32_reexec_emacs' instead of
'execvp'.  (Bug#17036)

src/emacs.c
src/w32.c
src/w32.h

index a16e702ab7b455d1a4ae3a594967ef75e840facc..8c897762a2bc607b9bfdcddbbbd224fbb7af87df 100644 (file)
@@ -159,6 +159,10 @@ Lisp_Object empty_unibyte_string, empty_multibyte_string;
 #ifdef WINDOWSNT
 /* Cache for externally loaded libraries.  */
 Lisp_Object Vlibrary_cache;
+/* Original command line string as received from the OS.  */
+static char *initial_cmdline;
+/* Original working directory when invoked.  */
+static const char *initial_wd;
 #endif
 
 struct gflags gflags;
@@ -1319,6 +1323,7 @@ main (int argc, char **argv)
        }
     }
   init_heap (use_dynamic_heap);
+  initial_cmdline = GetCommandLine ();
 #endif
 #if defined WINDOWSNT || defined HAVE_NTGUI
   /* Set global variables used to detect Windows version.  Do this as
@@ -1465,6 +1470,9 @@ main (int argc, char **argv)
 #endif
 
   emacs_wd = emacs_get_current_dir_name ();
+#ifdef WINDOWSNT
+  initial_wd = emacs_wd;
+#endif
 #ifdef HAVE_PDUMPER
   if (dumped_with_pdumper_p ())
     pdumper_record_wd (emacs_wd);
@@ -2811,7 +2819,11 @@ killed.  */
         (on some systems) with no argv.  */
       if (initial_argc < 1)
        error ("No command line arguments known; unable to re-execute Emacs");
+#ifdef WINDOWSNT
+      if (w32_reexec_emacs (initial_cmdline, initial_wd) < 1)
+#else
       if (execvp (*initial_argv, initial_argv) < 1)
+#endif
        error ("Unable to re-execute Emacs");
     }
 
index 0dc874eac40834615a63c7e64a131200cfbbbbc4..acd7d004e533a99490a7126697b7a78732b39962 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -10614,6 +10614,49 @@ realpath (const char *file_name, char *resolved_name)
   return xstrdup (tgt);
 }
 
+/* A replacement for Posix execvp, used to restart Emacs.  This is
+   needed because the low-level Windows API to start processes accepts
+   the command-line arguments as a single string, so we cannot safely
+   use the MSVCRT execvp emulation, because elements of argv[] that
+   have embedded blanks and tabs will not be passed correctly to the
+   restarted Emacs.  */
+int
+w32_reexec_emacs (char *cmd_line, const char *wdir)
+{
+  STARTUPINFO si;
+  SECURITY_ATTRIBUTES sec_attrs;
+  BOOL status;
+  PROCESS_INFORMATION proc_info;
+
+  GetStartupInfo (&si);                /* Use the same startup info as the caller.  */
+  sec_attrs.nLength = sizeof (sec_attrs);
+  sec_attrs.lpSecurityDescriptor = NULL;
+  sec_attrs.bInheritHandle = FALSE;
+
+  /* Make sure we are in the original directory, in case the command
+     line specifies the program as a relative file name.  */
+  chdir (wdir);
+
+  status = CreateProcess (NULL,                /* program */
+                         cmd_line,     /* command line */
+                         &sec_attrs,   /* process attributes */
+                         NULL,         /* thread attributes */
+                         TRUE,         /* inherit handles? */
+                         NORMAL_PRIORITY_CLASS,
+                         NULL,         /* environment */
+                         wdir,         /* initial directory */
+                         &si,          /* startup info */
+                         &proc_info);
+  if (status)
+    {
+      CloseHandle (proc_info.hThread);
+      CloseHandle (proc_info.hProcess);
+      exit (0);
+    }
+  errno = ENOEXEC;
+  return -1;
+}
+
 /*
        globals_of_w32 is used to initialize those global variables that
        must always be initialized on startup even when the global variable
index 4941170bdcf4855128eb65021422de91764a0969..dc91c595c433468a73a5ae2fff58afa108984b83 100644 (file)
--- a/src/w32.h
+++ b/src/w32.h
@@ -244,6 +244,9 @@ extern int w32_init_random (void *, ptrdiff_t);
 
 extern Lisp_Object w32_read_registry (HKEY, Lisp_Object, Lisp_Object);
 
+/* Used instead of execvp to restart Emacs.  */
+extern int w32_reexec_emacs (char *, const char *);
+
 #ifdef HAVE_GNUTLS
 #include <gnutls/gnutls.h>