changeset 21613:fe4f5bfae371

(w32_executable_type): Properly cast dos_header when making size comparison. (sys_spawnve): Update comments. (sys_select): Ignore children dead children with pending input. Delay sending SIGCHLD until all output has been read. (sys_kill): Sleep to allow focus change events to propagate. Use TerminateProcess on Win95. (int_from_hex, enum_locale_fn, Fw32_get_valid_locale_ids): New functions. (Vw32_valid_locale_ids): New variable. (Fw32_set_current_locale): Send message to input thread. (syms_of_ntproc): defsubr Sw32_get_valid_locale_ids.
author Geoff Voelker <voelker@cs.washington.edu>
date Fri, 17 Apr 1998 05:10:29 +0000
parents 24a01af0cd38
children 2624d8dcc73f
files src/w32proc.c
diffstat 1 files changed, 100 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/w32proc.c	Fri Apr 17 05:09:51 1998 +0000
+++ b/src/w32proc.c	Fri Apr 17 05:10:29 1998 +0000
@@ -45,6 +45,7 @@
 #include "systime.h"
 #include "syswait.h"
 #include "process.h"
+#include "w32term.h"
 
 /* Control whether spawnve quotes arguments as necessary to ensure
    correct parsing by child process.  Because not all uses of spawnve
@@ -606,7 +607,7 @@
 
       nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
 
-      if (nt_header > dos_header + executable.size) 
+      if ((char *) nt_header > (char *) dos_header + executable.size) 
 	{
 	  /* Some dos headers (pkunzip) have bogus e_lfanew fields.  */
 	  *is_dos_app = TRUE;
@@ -736,7 +737,7 @@
   unixtodos_filename (cmdname);
   argv[0] = cmdname;
 
-  /* Determine whether program is a 16-bit DOS executable, or a Win32
+  /* Determine whether program is a 16-bit DOS executable, or a w32
      executable that is implicitly linked to the Cygnus dll (implying it
      was compiled with the Cygnus GNU toolchain and hence relies on
      cygwin.dll to parse the command line - we use this to decide how to
@@ -771,7 +772,7 @@
      exactly, so we treat quotes at the beginning and end of arguments
      as embedded quotes.
 
-     The Win32 GNU-based library from Cygnus doubles quotes to escape
+     The w32 GNU-based library from Cygnus doubles quotes to escape
      them, while MSVC uses backslash for escaping.  (Actually the MSVC
      startup code does attempt to recognise doubled quotes and accept
      them, but gets it wrong and ends up requiring three quotes to get a
@@ -1109,8 +1110,17 @@
 	    else
 	      {
 		/* Unable to find something to wait on for this fd, skip */
+
+		/* Note that this is not a fatal error, and can in fact
+		   happen in unusual circumstances.  Specifically, if
+		   sys_spawnve fails, eg. because the program doesn't
+		   exist, and debug-on-error is t so Fsignal invokes a
+		   nested input loop, then the process output pipe is
+		   still included in input_wait_mask with no child_proc
+		   associated with it.  (It is removed when the debugger
+		   exits the nested input loop and the error is thrown.)  */
+
 		DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i));
-		abort ();
 	      }
 	  }
       }
@@ -1119,8 +1129,14 @@
   /* Add handles of child processes.  */
   nc = 0;
   for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
-    /* some child_procs might be sockets; ignore them */
-    if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess)
+    /* Some child_procs might be sockets; ignore them.  Also some
+       children may have died already, but we haven't finished reading
+       the process output; ignore them too.  */
+    if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess
+	&& (cp->fd < 0
+	    || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0
+	    || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)
+	)
       {
 	wait_hnd[nh + nc] = cp->procinfo.hProcess;
 	cps[nc] = cp;
@@ -1176,9 +1192,16 @@
       if (active >= nh)
 	{
 	  cp = cps[active - nh];
+
+	  /* We cannot always signal SIGCHLD immediately; if we have not
+	     finished reading the process output, we must delay sending
+	     SIGCHLD until we do.  */
+
+	  if (cp->fd >= 0 && (fd_info[cp->fd].flags & FILE_AT_EOF) == 0)
+	    fd_info[cp->fd].flags |= FILE_SEND_SIGCHLD;
 	  /* SIG_DFL for SIGCHLD is ignore */
-	  if (sig_handlers[SIGCHLD] != SIG_DFL
-	      && sig_handlers[SIGCHLD] != SIG_IGN)
+	  else if (sig_handlers[SIGCHLD] != SIG_DFL &&
+		   sig_handlers[SIGCHLD] != SIG_IGN)
 	    {
 #ifdef FULL_DEBUG
 	      DebPrint (("select calling SIGCHLD handler for pid %d\n",
@@ -1314,6 +1337,10 @@
 	      keybd_event (vk_break_code, break_scan_code, KEYEVENTF_KEYUP, 0);
 	      keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
 
+	      /* Sleep for a bit to give time for Emacs frame to respond
+		 to focus change events (if Emacs was active app).  */
+	      Sleep (10);
+
 	      SetForegroundWindow (foreground_window);
 	    }
 	}
@@ -1349,7 +1376,24 @@
    Could try to invoke DestroyVM through CallVxD.
 
 */
+#if 0
+	      /* On Win95, posting WM_QUIT causes the 16-bit subsystem
+		 to hang when cmdproxy is used in conjunction with
+		 command.com for an interactive shell.  Posting
+		 WM_CLOSE pops up a dialog that, when Yes is selected,
+		 does the same thing.  TerminateProcess is also less
+		 than ideal in that subprocesses tend to stick around
+		 until the machine is shutdown, but at least it
+		 doesn't freeze the 16-bit subsystem.  */
 	      PostMessage (cp->hwnd, WM_QUIT, 0xff, 0);
+#endif
+	      if (!TerminateProcess (proc_hand, 0xff))
+		{
+		  DebPrint (("sys_kill.TerminateProcess returned %d "
+			     "for pid %lu\n", GetLastError (), pid));
+		  errno = EINVAL;
+		  rc = -1;
+		}
 	    }
 	  else
 #endif
@@ -1696,6 +1740,48 @@
   return make_number (GetThreadLocale ());
 }
 
+DWORD int_from_hex (char * s)
+{
+  DWORD val = 0;
+  static char hex[] = "0123456789abcdefABCDEF";
+  char * p;
+
+  while (*s && (p = strchr(hex, *s)) != NULL)
+    {
+      unsigned digit = p - hex;
+      if (digit > 15)
+	digit -= 6;
+      val = val * 16 + digit;
+      s++;
+    }
+  return val;
+}
+
+/* We need to build a global list, since the EnumSystemLocale callback
+   function isn't given a context pointer.  */
+Lisp_Object Vw32_valid_locale_ids;
+
+BOOL CALLBACK enum_locale_fn (LPTSTR localeNum)
+{
+  DWORD id = int_from_hex (localeNum);
+  Vw32_valid_locale_ids = Fcons (make_number (id), Vw32_valid_locale_ids);
+  return TRUE;
+}
+
+DEFUN ("w32-get-valid-locale-ids", Fw32_get_valid_locale_ids, Sw32_get_valid_locale_ids, 0, 0, 0,
+  "Return list of all valid Windows locale ids.\n\
+Each id is a numerical value; use `w32-get-locale-info' to convert to a\n\
+human-readable form.")
+     ()
+{
+  Vw32_valid_locale_ids = Qnil;
+
+  EnumSystemLocales (enum_locale_fn, LCID_SUPPORTED);
+
+  Vw32_valid_locale_ids = Fnreverse (Vw32_valid_locale_ids);
+  return Vw32_valid_locale_ids;
+}
+
 
 DEFUN ("w32-get-default-locale-id", Fw32_get_default_locale_id, Sw32_get_default_locale_id, 0, 1, 0,
   "Return Windows locale id for default locale setting.\n\
@@ -1726,6 +1812,11 @@
   if (!SetThreadLocale (XINT (lcid)))
     return Qnil;
 
+  /* Need to set input thread locale if present.  */
+  if (dwWindowsThreadId)
+    /* Reply is not needed.  */
+    PostThreadMessage (dwWindowsThreadId, WM_EMACS_SETLOCALE, XINT (lcid), 0);
+
   return make_number (GetThreadLocale ());
 }
 
@@ -1745,6 +1836,7 @@
   defsubr (&Sw32_get_locale_info);
   defsubr (&Sw32_get_current_locale_id);
   defsubr (&Sw32_get_default_locale_id);
+  defsubr (&Sw32_get_valid_locale_ids);
   defsubr (&Sw32_set_current_locale);
 
   DEFVAR_LISP ("w32-quote-process-args", &Vw32_quote_process_args,