emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 5a63af876b: Fix 'restart-emacs' on MS-Windows


From: Eli Zaretskii
Subject: master 5a63af876b: Fix 'restart-emacs' on MS-Windows
Date: Sun, 17 Apr 2022 10:21:55 -0400 (EDT)

branch: master
commit 5a63af876bc131b07e066aa9d60780de0562bcb0
Author: Eli Zaretskii <eliz@gnu.org>
Commit: Eli Zaretskii <eliz@gnu.org>

    Fix 'restart-emacs' on MS-Windows
    
    * 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 | 12 ++++++++++++
 src/w32.c   | 43 +++++++++++++++++++++++++++++++++++++++++++
 src/w32.h   |  3 +++
 3 files changed, 58 insertions(+)

diff --git a/src/emacs.c b/src/emacs.c
index a16e702ab7..8c897762a2 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -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");
     }
 
diff --git a/src/w32.c b/src/w32.c
index 0dc874eac4..acd7d004e5 100644
--- 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
diff --git a/src/w32.h b/src/w32.h
index 4941170bdc..dc91c595c4 100644
--- 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>
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]