]> code.delx.au - gnu-emacs/blobdiff - src/w32proc.c
Do not copy X event in handle_one_xevent except KeyPress case.
[gnu-emacs] / src / w32proc.c
index 0fcb29930203d031e1264574eeabd1a764534f85..221b42fb7b262edc77e67794ab7ff184e3f503cc 100644 (file)
@@ -802,11 +802,59 @@ new_child (void)
   for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
     if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess == NULL)
       goto Initialize;
+  if (child_proc_count == MAX_CHILDREN)
+    {
+      int i = 0;
+      child_process *dead_cp = NULL;
+
+      DebPrint (("new_child: No vacant slots, looking for dead processes\n"));
+      for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
+       if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess)
+         {
+           DWORD status = 0;
+
+           if (!GetExitCodeProcess (cp->procinfo.hProcess, &status))
+             {
+               DebPrint (("new_child.GetExitCodeProcess: error %lu for PID %lu\n",
+                          GetLastError (), cp->procinfo.dwProcessId));
+               status = STILL_ACTIVE;
+             }
+           if (status != STILL_ACTIVE
+               || WaitForSingleObject (cp->procinfo.hProcess, 0) == WAIT_OBJECT_0)
+             {
+               DebPrint (("new_child: Freeing slot of dead process %d, fd %d\n",
+                          cp->procinfo.dwProcessId, cp->fd));
+               CloseHandle (cp->procinfo.hProcess);
+               cp->procinfo.hProcess = NULL;
+               CloseHandle (cp->procinfo.hThread);
+               cp->procinfo.hThread = NULL;
+               /* Free up to 2 dead slots at a time, so that if we
+                  have a lot of them, they will eventually all be
+                  freed when the tornado ends.  */
+               if (i == 0)
+                 dead_cp = cp;
+               else
+                 break;
+               i++;
+             }
+         }
+      if (dead_cp)
+       {
+         cp = dead_cp;
+         goto Initialize;
+       }
+    }
   if (child_proc_count == MAX_CHILDREN)
     return NULL;
   cp = &child_procs[child_proc_count++];
 
  Initialize:
+  /* Last opportunity to avoid leaking handles before we forget them
+     for good.  */
+  if (cp->procinfo.hProcess)
+    CloseHandle (cp->procinfo.hProcess);
+  if (cp->procinfo.hThread)
+    CloseHandle (cp->procinfo.hThread);
   memset (cp, 0, sizeof (*cp));
   cp->fd = -1;
   cp->pid = -1;
@@ -942,6 +990,18 @@ find_child_pid (DWORD pid)
   return NULL;
 }
 
+void
+release_listen_threads (void)
+{
+  int i;
+
+  for (i = child_proc_count - 1; i >= 0; i--)
+    {
+      if (CHILD_ACTIVE (&child_procs[i])
+         && (fd_info[child_procs[i].fd].flags & FILE_LISTEN))
+       child_procs[i].status = STATUS_READ_ERROR;
+    }
+}
 
 /* Thread proc for child process and socket reader threads. Each thread
    is normally blocked until woken by select() to check for input by
@@ -979,8 +1039,9 @@ reader_thread (void *arg)
         read-ahead has completed, whether successfully or not. */
       if (!SetEvent (cp->char_avail))
         {
-         DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
-                    GetLastError (), cp->fd));
+         DebPrint (("reader_thread.SetEvent(0x%x) failed with %lu for fd %ld (PID %d)\n",
+                    (DWORD_PTR)cp->char_avail, GetLastError (),
+                    cp->fd, cp->pid));
          return 1;
        }
 
@@ -1083,7 +1144,7 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
   return FALSE;
 }
 
-/* create_child doesn't know what emacs' file handle will be for waiting
+/* create_child doesn't know what emacs's file handle will be for waiting
    on output from the child, so we need to make this additional call
    to register the handle with the process
    This way the select emulator knows how to match file handles with
@@ -1541,7 +1602,6 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
   child_process *cp;
   int is_dos_app, is_cygnus_app, is_gui_app;
   int do_quoting = 0;
-  char escape_char;
   /* We pass our process ID to our children by setting up an environment
      variable in their environment.  */
   char ppid_env_var_buffer[64];
@@ -1554,6 +1614,8 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
      Some extra whitespace characters need quoting in Cygwin programs,
      so this list is conditionally modified below.  */
   char *sepchars = " \t*?";
+  /* This is for native w32 apps; modified below for Cygwin apps.  */
+  char escape_char = '\\';
 
   /* We don't care about the other modes */
   if (mode != _P_NOWAIT)
@@ -1866,7 +1928,7 @@ extern int proc_buffered_char[];
 
 int
 sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
-           EMACS_TIME *timeout, void *ignored)
+           struct timespec *timeout, void *ignored)
 {
   SELECT_TYPE orfds;
   DWORD timeout_ms, start_time;
@@ -2007,7 +2069,7 @@ count_children:
     /* 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
+    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)
@@ -2213,12 +2275,42 @@ sys_kill (pid_t pid, int sig)
     pid = -pid;
 
   /* Only handle signals that will result in the process dying */
-  if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
+  if (sig != 0
+      && sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
     {
       errno = EINVAL;
       return -1;
     }
 
+  if (sig == 0)
+    {
+      /* It will take _some_ time before PID 4 or less on Windows will
+        be Emacs...  */
+      if (pid <= 4)
+       {
+         errno = EPERM;
+         return -1;
+       }
+      proc_hand = OpenProcess (PROCESS_QUERY_INFORMATION, 0, pid);
+      if (proc_hand == NULL)
+        {
+         DWORD err = GetLastError ();
+
+         switch (err)
+           {
+           case ERROR_ACCESS_DENIED: /* existing process, but access denied */
+             errno = EPERM;
+             return -1;
+           case ERROR_INVALID_PARAMETER: /* process PID does not exist */
+             errno = ESRCH;
+             return -1;
+           }
+       }
+      else
+       CloseHandle (proc_hand);
+      return 0;
+    }
+
   cp = find_child_pid (pid);
   if (cp == NULL)
     {
@@ -2557,8 +2649,9 @@ All path elements in FILENAME are converted to their short names.  */)
   if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0)
     return Qnil;
 
-  dostounix_filename (shortname);
+  dostounix_filename (shortname, 0);
 
+  /* No need to DECODE_FILE, because 8.3 names are pure ASCII.   */
   return build_string (shortname);
 }
 
@@ -2585,7 +2678,7 @@ All path elements in FILENAME are converted to their long names.  */)
   if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH))
     return Qnil;
 
-  dostounix_filename (longname);
+  dostounix_filename (longname, 0);
 
   /* If we were passed only a drive, make sure that a slash is not appended
      for consistency with directories.  Allow for drive mapping via SUBST