emacs-devel
[Top][All Lists]
Advanced

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

Re: delete-process bug


From: Stefan Monnier
Subject: Re: delete-process bug
Date: Thu, 25 May 2006 10:55:08 -0400
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux)

> This is  not really  due to my  patch. However,  it shows a  real race
> condition in process management of Emacs:
[...]
> After an hour of debugging, I can propose a small change that fixes
> this bug and lets no room for any other race condition of that kind,
> AFAICT.
[...]
> +     * process.c (Fdelete_process): Wait for process termination to
> +     avoid `sigchld_handler' to consider the process to be synchronous.

I don't think it's a good idea.  The process might not die in response to
delete-process, so we would end up waiting "indefinitely".

I think in order to avoid such race-conditions without waiting for the
process's death, we'll need to remember those processes that were deleted
but aren't dead yet.  Of course, it goes against the docstring of
`delete-process' which says "forget about it immediately".  But we don't
need to keep the whole process around; just the PID should be enough, kept
in a list of "deleted but not dead" PIDs.  See sample patch below.


        Stefan


--- process.c   12 mai 2006 11:54:58 -0400      1.481
+++ process.c   25 mai 2006 10:51:51 -0400      
@@ -778,6 +778,13 @@
   return proc;
 }
 
+/* Fdelete_process promises to immediately forget about the process, but in
+   reality Emacs needs to remember those processes until they die, otherwise
+   it doesn't know what to do with the SIGCHLD signal and might be tempted
+   to interpret that signal as applying to some other non-deleted
+   process ;-(.  */
+static Lisp_Object live_deleted_processes;
+
 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
@@ -800,6 +807,9 @@
   else if (XINT (p->infd) >= 0)
     {
       Fkill_process (process, Qnil);
+      live_deleted_processes = Fcons (make_number (p->pid),
+                                     /* GC previous elements.  */
+                                     Fdelq (Qnil, live_deleted_processes));
       /* Do this now, since remove_process will make sigchld_handler do 
nothing.  */
       p->status
        = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
@@ -6373,6 +6383,13 @@
 
       /* Find the process that signaled us, and record its status.  */
 
+      /* Maybe the process was already passed to Fdelete_process.  */
+      tail = Fmemq (make_number (pid), live_deleted_processes);
+      if (!NILP (tail)) {
+       Fsetcar (tail, Qnil);
+       return;
+      }
+
       p = 0;
       for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCDR (tail))
        {
@@ -7357,6 +7374,7 @@
 void
 init_process ()
 {
+  live_deleted_processes = Qnil;
 }
 
 void




reply via email to

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