emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] trunk r113479: Avoid vfork-related deadlock more cleanly.


From: Paul Eggert
Subject: [Emacs-diffs] trunk r113479: Avoid vfork-related deadlock more cleanly.
Date: Sun, 21 Jul 2013 06:54:00 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 113479
revision-id: address@hidden
parent: address@hidden
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Sat 2013-07-20 23:53:47 -0700
message:
  Avoid vfork-related deadlock more cleanly.
  
  * callproc.c (child_setup): When the child's exec fails, output
  the program name, as that's more useful.  Use O_NONBLOCK to avoid
  deadlock.
  * process.c (create_process_1): Remove; no longer needed.
  (create_process): Remove timer hack; no longer needed, now that
  the child avoids deadlock.
modified:
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/callproc.c                 callproc.c-20091113204419-o5vbwnq5f7feedwu-248
  src/process.c                  process.c-20091113204419-o5vbwnq5f7feedwu-462
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-07-21 02:53:19 +0000
+++ b/src/ChangeLog     2013-07-21 06:53:47 +0000
@@ -1,3 +1,13 @@
+2013-07-21  Paul Eggert  <address@hidden>
+
+       Avoid vfork-related deadlock more cleanly.
+       * callproc.c (child_setup): When the child's exec fails, output
+       the program name, as that's more useful.  Use O_NONBLOCK to avoid
+       deadlock.
+       * process.c (create_process_1): Remove; no longer needed.
+       (create_process): Remove timer hack; no longer needed, now that
+       the child avoids deadlock.
+
 2013-07-20  Glenn Morris  <address@hidden>
 
        * image.c (Fimage_flush): Fix doc typo.

=== modified file 'src/callproc.c'
--- a/src/callproc.c    2013-07-17 04:37:27 +0000
+++ b/src/callproc.c    2013-07-21 06:53:47 +0000
@@ -1193,6 +1193,7 @@
 {
   char **env;
   char *pwd_var;
+  int exec_errno;
 #ifdef WINDOWSNT
   int cpid;
   HANDLE handles[3];
@@ -1368,13 +1369,16 @@
   tcsetpgrp (0, pid);
 
   execve (new_argv[0], new_argv, env);
-
-  /* Don't output the program name here, as it can be arbitrarily long,
-     and a long write from a vforked child to its parent can cause a
-     deadlock.  */
-  emacs_perror ("child process");
-
-  _exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+  exec_errno = errno;
+
+  /* Avoid deadlock if the child's perror writes to a full pipe; the
+     pipe's reader is the parent, but with vfork the parent can't
+     run until the child exits.  Truncate the diagnostic instead.  */
+  fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
+
+  errno = exec_errno;
+  emacs_perror (new_argv[0]);
+  _exit (exec_errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
 
 #else /* MSDOS */
   pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env);

=== modified file 'src/process.c'
--- a/src/process.c     2013-07-20 15:33:00 +0000
+++ b/src/process.c     2013-07-21 06:53:47 +0000
@@ -1599,12 +1599,6 @@
     remove_process (proc);
 }
 
-static void
-create_process_1 (struct atimer *timer)
-{
-  /* Nothing to do.  */
-}
-
 
 static void
 create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
@@ -1841,14 +1835,13 @@
   unblock_child_signal ();
   unblock_input ();
 
+  if (forkin >= 0)
+    emacs_close (forkin);
+  if (forkin != forkout && forkout >= 0)
+    emacs_close (forkout);
+
   if (pid < 0)
-    {
-      if (forkin >= 0)
-       emacs_close (forkin);
-      if (forkin != forkout && forkout >= 0)
-       emacs_close (forkout);
-      report_file_errno ("Doing vfork", Qnil, vfork_errno);
-    }
+    report_file_errno ("Doing vfork", Qnil, vfork_errno);
   else
     {
       /* vfork succeeded.  */
@@ -1857,26 +1850,6 @@
       register_child (pid, inchannel);
 #endif /* WINDOWSNT */
 
-      /* If the subfork execv fails, and it exits,
-        this close hangs.  I don't know why.
-        So have an interrupt jar it loose.  */
-      {
-       struct atimer *timer;
-       EMACS_TIME offset = make_emacs_time (1, 0);
-
-       stop_polling ();
-       timer = start_atimer (ATIMER_RELATIVE, offset, create_process_1, 0);
-
-       if (forkin >= 0)
-         emacs_close (forkin);
-
-       cancel_atimer (timer);
-       start_polling ();
-      }
-
-      if (forkin != forkout && forkout >= 0)
-       emacs_close (forkout);
-
       pset_tty_name (XPROCESS (process), lisp_pty_name);
 
 #ifndef WINDOWSNT


reply via email to

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