changeset 71140:80310801887e

2006-06-01 Micha¸«³l Cadilhac <michael.cadilhac@lrde.org> (deleted_pid_list): New variable to store the pids of deleted processes. Declare it only if SIGCHLD is defined. (init_process): Initialize it. (syms_of_process): Staticpro it. (Fdelete_process): Add pid of the deleted process to it. Check after the addition and before the kill if the process is already stopped, in which case it is deleted from the list and not killed. (sigchld_handler): Define it only if SIGCHLD is. Search the process that signaled Emacs in `deleted_pid_list' before `Vprocess_alist'. Original idea by Stefan Monnier.
author Kim F. Storm <storm@cua.dk>
date Thu, 01 Jun 2006 14:08:25 +0000
parents 355a8928782c
children 8b67793e19f3
files src/process.c
diffstat 1 files changed, 57 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/process.c	Thu Jun 01 14:07:33 2006 +0000
+++ b/src/process.c	Thu Jun 01 14:08:25 2006 +0000
@@ -778,6 +778,16 @@
   return proc;
 }
 
+
+#ifdef SIGCHLD
+/* Fdelete_process promises to immediately forget about the process, but in
+   reality, Emacs needs to remember those processes until they have been
+   treated by sigchld_handler; otherwise this handler would consider the
+   process as being synchronous and say that the synchronous process is
+   dead.  */
+static Lisp_Object deleted_pid_list;
+#endif
+
 DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
        doc: /* Delete PROCESS: kill it and forget about it immediately.
 PROCESS may be a process, a buffer, the name of a process or buffer, or
@@ -799,12 +809,31 @@
     }
   else if (XINT (p->infd) >= 0)
     {
-      Fkill_process (process, Qnil);
-      /* Do this now, since remove_process will make sigchld_handler do nothing.  */
-      p->status
-	= Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
-      XSETINT (p->tick, ++process_tick);
-      status_notify (p);
+#ifdef SIGCHLD
+      Lisp_Object symbol;
+
+      /* No problem storing the pid here, as it is still in Vprocess_alist.  */
+      deleted_pid_list = Fcons (make_fixnum_or_float (p->pid),
+				/* GC treated elements set to nil.  */
+				Fdelq (Qnil, deleted_pid_list));
+      /* If the process has already signaled, remove it from the list.  */
+      if (p->raw_status_new)
+	update_status (p);
+      symbol = p->status;
+      if (CONSP (p->status))
+	symbol = XCAR (p->status);
+      if (EQ (symbol, Qsignal) || EQ (symbol, Qexit))
+	Fdelete (make_fixnum_or_float (p->pid), deleted_pid_list);
+      else
+#endif
+	{
+	  Fkill_process (process, Qnil);
+	  /* Do this now, since remove_process will make sigchld_handler do nothing.  */
+	  p->status
+	    = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
+	  XSETINT (p->tick, ++process_tick);
+	  status_notify (p);
+	}
     }
   remove_process (process);
   return Qnil;
@@ -6335,6 +6364,7 @@
    ** Malloc WARNING: This should never call malloc either directly or
    indirectly; if it does, that is a bug  */
 
+#ifdef SIGCHLD
 SIGTYPE
 sigchld_handler (signo)
      int signo;
@@ -6392,6 +6422,15 @@
 
       /* Find the process that signaled us, and record its status.  */
 
+      /* The process can have been deleted by Fdelete_process.  */
+      tail = Fmember (make_fixnum_or_float (pid), deleted_pid_list);
+      if (!NILP (tail))
+	{
+	  Fsetcar (tail, Qnil);
+	  goto sigchld_end_of_loop;
+	}
+
+      /* Otherwise, if it is asynchronous, it is in Vprocess_alist.  */
       p = 0;
       for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail))
 	{
@@ -6443,8 +6482,8 @@
 	    EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
 	}
 
-	/* There was no asynchronous process found for that id.  Check
-	   if we have a synchronous process.  */
+      /* There was no asynchronous process found for that pid: we have
+	 a synchronous process.  */
       else
 	{
 	  synch_process_alive = 0;
@@ -6461,6 +6500,9 @@
 	    EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
 	}
 
+    sigchld_end_of_loop:
+      ;
+
       /* On some systems, we must return right away.
 	 If any more processes want to signal us, we will
 	 get another signal.
@@ -6477,6 +6519,7 @@
 #endif /* USG, but not HPUX with WNOHANG */
     }
 }
+#endif /* SIGCHLD */
 
 
 static Lisp_Object
@@ -6862,6 +6905,9 @@
   FD_SET (0, &input_wait_mask);
 
   Vprocess_alist = Qnil;
+#ifdef SIGCHLD
+  deleted_pid_list = Qnil;
+#endif
   for (i = 0; i < MAXDESC; i++)
     {
       chan_process[i] = Qnil;
@@ -7000,6 +7046,9 @@
   staticpro (&Qlast_nonmenu_event);
 
   staticpro (&Vprocess_alist);
+#ifdef SIGCHLD
+  staticpro (&deleted_pid_list);
+#endif
 
   DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
 	       doc: /* *Non-nil means delete processes immediately when they exit.