]> git.eshelyaron.com Git - emacs.git/commitdiff
Don't kill already-reaped process.
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 27 May 2014 03:46:30 +0000 (20:46 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 27 May 2014 03:46:30 +0000 (20:46 -0700)
* process.c (process_send_signal): Fix race condition where a
subprocess was reaped by a signal handler between the check for
liveness and calling 'kill', which meant that Emacs could in
theory kill an innocent bystander process.  Do the fix by blocking
SIGCHLD in a critical section that checks liveness before killing.

Fixes: debbugs:17561
src/ChangeLog
src/process.c

index 247ec1c34b4fb5aa97d39ff35500b33ed7106a00..d2db6ccebd685e14eda3bd5cb2aa8ec435e003a3 100644 (file)
@@ -1,3 +1,12 @@
+2014-05-27  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Don't kill already-reaped process (Bug#17561).
+       * process.c (process_send_signal): Fix race condition where a
+       subprocess was reaped by a signal handler between the check for
+       liveness and calling 'kill', which meant that Emacs could in
+       theory kill an innocent bystander process.  Do the fix by blocking
+       SIGCHLD in a critical section that checks liveness before killing.
+
 2014-05-26  Eli Zaretskii  <eliz@gnu.org>
 
        * w32.c (_ANONYMOUS_UNION, _ANONYMOUS_STRUCT): Define only if
index fdb0501f9ecdd897a98ef9645f25b18efad72177..561aefc6c9f5c14ef83e6fd8004d4293b157f943 100644 (file)
@@ -5833,30 +5833,25 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
     }
 #endif
 
+#ifdef TIOCSIGSEND
+  /* Work around a HP-UX 7.0 bug that mishandles signals to subjobs.
+     We don't know whether the bug is fixed in later HP-UX versions.  */
+  if (! NILP (current_group) && ioctl (p->infd, TIOCSIGSEND, signo) != -1)
+    return;
+#endif
+
   /* If we don't have process groups, send the signal to the immediate
      subprocess.  That isn't really right, but it's better than any
      obvious alternative.  */
-  if (no_pgrp)
-    {
-      kill (p->pid, signo);
-      return;
-    }
+  pid_t pid = no_pgrp ? gid : - gid;
 
-  /* gid may be a pid, or minus a pgrp's number */
-#ifdef TIOCSIGSEND
-  if (!NILP (current_group))
-    {
-      if (ioctl (p->infd, TIOCSIGSEND, signo) == -1)
-       kill (-gid, signo);
-    }
-  else
-    {
-      gid = - p->pid;
-      kill (gid, signo);
-    }
-#else /* ! defined (TIOCSIGSEND) */
-  kill (-gid, signo);
-#endif /* ! defined (TIOCSIGSEND) */
+  /* Do not kill an already-reaped process, as that could kill an
+     innocent bystander that happens to have the same process ID.  */
+  sigset_t oldset;
+  block_child_signal (&oldset);
+  if (p->alive)
+    kill (pid, signo);
+  unblock_child_signal (&oldset);
 }
 
 DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0,