unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#554: OSX: with-temp-buffer kills unrelated processes
@ 2008-07-13 17:39 Markus Triska
  2008-07-14 10:26 ` YAMAMOTO Mitsuharu
  0 siblings, 1 reply; 5+ messages in thread
From: Markus Triska @ 2008-07-13 17:39 UTC (permalink / raw)
  To: bug-gnu-emacs

Let w.el consist of the following forms:

 (start-process "bc1" (current-buffer) "bc")

 (with-temp-buffer (start-process "bc2" (current-buffer) "bc"))

When I do "emacs -Q w.el", and press C-M-x on the first form, "bc"
(the GNU arbitrary precision calculator) is started and puts its
start-up message at the end of the buffer (you can also use any other
program that waits for further input). When I then press C-M-x on the
second form, the first process receives SIGHUP, and the message reads:

 "Process bc1 hangup"

I can reproduce this with Emacs 22.2 and latest CVS on OSX. I tried to
trace it in gdb by putting a breakpoint at process_send_signal, but
couldn't reproduce it in the debugger. Otherwise it works every time.

In GNU Emacs 22.2.1 (i386-apple-darwin8.11.1)
 of 2008-05-19 on mt-computer.local
configured using `configure  '--prefix=/opt/local' '--without-x' '--without-carbon' 'CC=/usr/bin/gcc-4.0' 'CFLAGS=-O2' 'LDFLAGS=-L/opt/local/lib' 'CPPFLAGS=-I/opt/local/include' 'CPP=/usr/bin/cpp-4.0''

Important settings:
  value of $LC_ALL: nil
  value of $LC_COLLATE: nil
  value of $LC_CTYPE: nil
  value of $LC_MESSAGES: nil
  value of $LC_MONETARY: nil
  value of $LC_NUMERIC: nil
  value of $LC_TIME: nil
  value of $LANG: nil
  locale-coding-system: nil
  default-enable-multibyte-characters: t







^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#554: OSX: with-temp-buffer kills unrelated processes
  2008-07-13 17:39 bug#554: OSX: with-temp-buffer kills unrelated processes Markus Triska
@ 2008-07-14 10:26 ` YAMAMOTO Mitsuharu
  2008-07-16  9:17   ` YAMAMOTO Mitsuharu
  0 siblings, 1 reply; 5+ messages in thread
From: YAMAMOTO Mitsuharu @ 2008-07-14 10:26 UTC (permalink / raw)
  To: Markus Triska, 554

>>>>> On Sun, 13 Jul 2008 19:39:57 +0200 (CEST), Markus Triska <markus.triska@gmx.at> said:
--text follows this line--
> Let w.el consist of the following forms:
>  (start-process "bc1" (current-buffer) "bc")

>  (with-temp-buffer (start-process "bc2" (current-buffer) "bc"))

> When I do "emacs -Q w.el", and press C-M-x on the first form, "bc"
> (the GNU arbitrary precision calculator) is started and puts its
> start-up message at the end of the buffer (you can also use any other
> program that waits for further input). When I then press C-M-x on the
> second form, the first process receives SIGHUP, and the message reads:

>  "Process bc1 hangup"

> I can reproduce this with Emacs 22.2 and latest CVS on OSX. I tried to
> trace it in gdb by putting a breakpoint at process_send_signal, but
> couldn't reproduce it in the debugger. Otherwise it works every time.

Just some analysis: not a solution I'm afraid.

It seems that the child process receives SIGHUP before it calls
execvp.  As the child process is still running the Emacs executable,
it sends SIGHUP to all the subprocesses when it receives SIGHUP
(fatal_error_signal -> shut_down_emacs -> kill_buffer_processes).

A similar problem can be found in following example:

  (process-running-child-p (start-process "bc1" (current-buffer) "bc"))
  => t

  (process-running-child-p (prog1 (start-process "bc1" (current-buffer) "bc")
			     (sleep-for 1)))
  => nil

I think these behaviors are not observable in other platforms, because
they use vfork, and the parent side effectively blocks until the child
side calls execvp or others in its typical implementations.  Emacs on
Darwin is using fork instead of vfork because the latter had (or
have?) some problems I'm not familiar with.

				     YAMAMOTO Mitsuharu
				mituharu@math.s.chiba-u.ac.jp






^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#554: OSX: with-temp-buffer kills unrelated processes
  2008-07-14 10:26 ` YAMAMOTO Mitsuharu
@ 2008-07-16  9:17   ` YAMAMOTO Mitsuharu
  2008-07-16 15:27     ` Markus Triska
  0 siblings, 1 reply; 5+ messages in thread
From: YAMAMOTO Mitsuharu @ 2008-07-16  9:17 UTC (permalink / raw)
  To: Markus Triska, 554

>>>>> On Mon, 14 Jul 2008 19:26:52 +0900, YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> said:

> It seems that the child process receives SIGHUP before it calls
> execvp.  As the child process is still running the Emacs executable,
> it sends SIGHUP to all the subprocesses when it receives SIGHUP
> (fatal_error_signal -> shut_down_emacs -> kill_buffer_processes).

> I think these behaviors are not observable in other platforms,
> because they use vfork, and the parent side effectively blocks until
> the child side calls execvp or others in its typical
> implementations.  Emacs on Darwin is using fork instead of vfork
> because the latter had (or have?) some problems I'm not familiar
> with.

OK, close-on-exec seems to be usable for the `fork' case.  How about
the patch below?

				     YAMAMOTO Mitsuharu
				mituharu@math.s.chiba-u.ac.jp

Index: src/callproc.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/callproc.c,v
retrieving revision 1.221.2.3
diff -c -p -r1.221.2.3 callproc.c
*** src/callproc.c	8 Jan 2008 04:30:19 -0000	1.221.2.3
--- src/callproc.c	16 Jul 2008 08:03:57 -0000
*************** static int relocate_fd ();
*** 1192,1199 ****
     Therefore, the superior process must save and restore the value
     of environ around the vfork and the call to this function.
  
!    SET_PGRP is nonzero if we should put the subprocess into a separate
!    process group.
  
     CURRENT_DIR is an elisp string giving the path of the current
     directory the subprocess should have.  Since we can't really signal
--- 1192,1199 ----
     Therefore, the superior process must save and restore the value
     of environ around the vfork and the call to this function.
  
!    RET_ON_FAIL is nonzero if we should return from the function on
!    failure of execvp rather than calling _exit.
  
     CURRENT_DIR is an elisp string giving the path of the current
     directory the subprocess should have.  Since we can't really signal
*************** static int relocate_fd ();
*** 1201,1210 ****
     executable directory by the parent.  */
  
  int
! child_setup (in, out, err, new_argv, set_pgrp, current_dir)
       int in, out, err;
       register char **new_argv;
!      int set_pgrp;
       Lisp_Object current_dir;
  {
    char **env;
--- 1201,1210 ----
     executable directory by the parent.  */
  
  int
! child_setup (in, out, err, new_argv, ret_on_fail, current_dir)
       int in, out, err;
       register char **new_argv;
!      int ret_on_fail;
       Lisp_Object current_dir;
  {
    char **env;
*************** child_setup (in, out, err, new_argv, set
*** 1412,1418 ****
    emacs_write (1, "Can't exec program: ", 20);
    emacs_write (1, new_argv[0], strlen (new_argv[0]));
    emacs_write (1, "\n", 1);
!   _exit (1);
  #endif /* not WINDOWSNT */
  #endif /* not MSDOS */
  }
--- 1412,1419 ----
    emacs_write (1, "Can't exec program: ", 20);
    emacs_write (1, new_argv[0], strlen (new_argv[0]));
    emacs_write (1, "\n", 1);
!   if (!ret_on_fail)
!     _exit (1);
  #endif /* not WINDOWSNT */
  #endif /* not MSDOS */
  }
Index: src/process.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/process.c,v
retrieving revision 1.512.2.12
diff -c -p -r1.512.2.12 process.c
*** src/process.c	27 Feb 2008 15:07:14 -0000	1.512.2.12
--- src/process.c	16 Jul 2008 08:03:58 -0000
*************** create_process (process, new_argv, curre
*** 1842,1847 ****
--- 1842,1850 ----
    int inchannel, outchannel;
    pid_t pid;
    int sv[2];
+ #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+   int wait_child_setup[2];
+ #endif
  #ifdef POSIX_SIGNALS
    sigset_t procmask;
    sigset_t blocked;
*************** create_process (process, new_argv, curre
*** 1884,1895 ****
  #endif
        if (forkin < 0)
  	report_file_error ("Opening pty", Qnil);
- #if defined (RTU) || defined (UNIPLUS) || defined (DONT_REOPEN_PTY)
-       /* In the case that vfork is defined as fork, the parent process
- 	 (Emacs) may send some data before the child process completes
- 	 tty options setup.  So we setup tty before forking.  */
-       child_setup_tty (forkout);
- #endif /* RTU or UNIPLUS or DONT_REOPEN_PTY */
  #else
        forkin = forkout = -1;
  #endif /* not USG, or USG_SUBTTY_WORKS */
--- 1887,1892 ----
*************** create_process (process, new_argv, curre
*** 1924,1929 ****
--- 1921,1945 ----
      }
  #endif /* not SKTPAIR */
  
+ #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+     {
+       int tem;
+ 
+       tem = pipe (wait_child_setup);
+       if (tem < 0)
+ 	report_file_error ("Creating pipe", Qnil);
+       tem = fcntl (wait_child_setup[1], F_GETFD, 0);
+       if (tem >= 0)
+ 	tem = fcntl (wait_child_setup[1], F_SETFD, tem | FD_CLOEXEC);
+       if (tem < 0)
+ 	{
+ 	  emacs_close (wait_child_setup[0]);
+ 	  emacs_close (wait_child_setup[1]);
+ 	  report_file_error ("Setting file descriptor flags", Qnil);
+ 	}
+     }
+ #endif
+ 
  #if 0
    /* Replaced by close_process_descs */
    set_exclusive_use (inchannel);
*************** create_process (process, new_argv, curre
*** 2174,2189 ****
  #endif /* SIGCHLD */
  #endif /* !POSIX_SIGNALS */
  
- #if !defined (RTU) && !defined (UNIPLUS) && !defined (DONT_REOPEN_PTY)
  	if (pty_flag)
  	  child_setup_tty (xforkout);
- #endif /* not RTU and not UNIPLUS and not DONT_REOPEN_PTY */
  #ifdef WINDOWSNT
  	pid = child_setup (xforkin, xforkout, xforkout,
  			   new_argv, 1, current_dir);
  #else  /* not WINDOWSNT */
  	child_setup (xforkin, xforkout, xforkout,
  		     new_argv, 1, current_dir);
  #endif /* not WINDOWSNT */
        }
      environ = save_environ;
--- 2190,2210 ----
  #endif /* SIGCHLD */
  #endif /* !POSIX_SIGNALS */
  
  	if (pty_flag)
  	  child_setup_tty (xforkout);
  #ifdef WINDOWSNT
  	pid = child_setup (xforkin, xforkout, xforkout,
  			   new_argv, 1, current_dir);
  #else  /* not WINDOWSNT */
+ #ifdef FD_CLOEXEC
+ 	emacs_close (wait_child_setup[0]);
+ #endif
  	child_setup (xforkin, xforkout, xforkout,
  		     new_argv, 1, current_dir);
+ #ifdef FD_CLOEXEC
+ 	emacs_close (wait_child_setup[1]);
+ #endif
+ 	_exit (1);
  #endif /* not WINDOWSNT */
        }
      environ = save_environ;
*************** create_process (process, new_argv, curre
*** 2235,2240 ****
--- 2256,2276 ----
        else
  #endif
  	XPROCESS (process)->tty_name = Qnil;
+ 
+ #if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+       /* Wait for child_setup to complete in case that vfork is
+ 	 actually defined as fork.  The descriptor wait_child_setup[1]
+ 	 of a pipe is closed at the child side either by close-on-exec
+ 	 on successful execvp or by the explicit emacs_close call
+ 	 before _exit above.  */
+       {
+ 	char dummy;
+ 
+ 	emacs_close (wait_child_setup[1]);
+ 	emacs_read (wait_child_setup[0], &dummy, 1);
+ 	emacs_close (wait_child_setup[0]);
+       }
+ #endif
      }
  
    /* Restore the signal state whether vfork succeeded or not.






^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#554: OSX: with-temp-buffer kills unrelated processes
  2008-07-16  9:17   ` YAMAMOTO Mitsuharu
@ 2008-07-16 15:27     ` Markus Triska
  2008-07-17  1:51       ` YAMAMOTO Mitsuharu
  0 siblings, 1 reply; 5+ messages in thread
From: Markus Triska @ 2008-07-16 15:27 UTC (permalink / raw)
  To: YAMAMOTO Mitsuharu; +Cc: 554

YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> writes:

> OK, close-on-exec seems to be usable for the `fork' case.  How about
> the patch below?

Thank you very much; I've tested the following adapted version of your
patch with the latest CVS trunk of Emacs, and the problem seems gone.

All the best,
Markus


diff --git a/src/callproc.c b/src/callproc.c
index a6de766..3d61e64 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1047,8 +1047,8 @@ add_env (char **env, char **new_env, char *string)
    Therefore, the superior process must save and restore the value
    of environ around the vfork and the call to this function.
 
-   SET_PGRP is nonzero if we should put the subprocess into a separate
-   process group.
+   RET_ON_FAIL is nonzero if we should return from the function on
+   failure of execvp rather than calling _exit.
 
    CURRENT_DIR is an elisp string giving the path of the current
    directory the subprocess should have.  Since we can't really signal
@@ -1056,10 +1056,10 @@ add_env (char **env, char **new_env, char *string)
    executable directory by the parent.  */
 
 int
-child_setup (in, out, err, new_argv, set_pgrp, current_dir)
+child_setup (in, out, err, new_argv, ret_on_fail, current_dir)
      int in, out, err;
      register char **new_argv;
-     int set_pgrp;
+     int ret_on_fail;
      Lisp_Object current_dir;
 {
   char **env;
@@ -1291,7 +1291,8 @@ child_setup (in, out, err, new_argv, set_pgrp, current_dir)
   emacs_write (1, "Can't exec program: ", 20);
   emacs_write (1, new_argv[0], strlen (new_argv[0]));
   emacs_write (1, "\n", 1);
-  _exit (1);
+  if (!ret_on_fail)
+    _exit (1);
 #endif /* not WINDOWSNT */
 #endif /* not MSDOS */
 }
diff --git a/src/process.c b/src/process.c
index c82584a..b0bebeb 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1851,6 +1851,9 @@ create_process (process, new_argv, current_dir)
   int inchannel, outchannel;
   pid_t pid;
   int sv[2];
+#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+  int wait_child_setup[2];
+#endif
 #ifdef POSIX_SIGNALS
   sigset_t procmask;
   sigset_t blocked;
@@ -1893,12 +1896,6 @@ create_process (process, new_argv, current_dir)
 #endif
       if (forkin < 0)
 	report_file_error ("Opening pty", Qnil);
-#if defined (DONT_REOPEN_PTY)
-      /* In the case that vfork is defined as fork, the parent process
-	 (Emacs) may send some data before the child process completes
-	 tty options setup.  So we setup tty before forking.  */
-      child_setup_tty (forkout);
-#endif /* DONT_REOPEN_PTY */
 #else
       forkin = forkout = -1;
 #endif /* not USG, or USG_SUBTTY_WORKS */
@@ -1924,6 +1921,25 @@ create_process (process, new_argv, current_dir)
       forkin = sv[0];
     }
 
+#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+    {
+      int tem;
+
+      tem = pipe (wait_child_setup);
+      if (tem < 0)
+	report_file_error ("Creating pipe", Qnil);
+      tem = fcntl (wait_child_setup[1], F_GETFD, 0);
+      if (tem >= 0)
+	tem = fcntl (wait_child_setup[1], F_SETFD, tem | FD_CLOEXEC);
+      if (tem < 0)
+	{
+	  emacs_close (wait_child_setup[0]);
+	  emacs_close (wait_child_setup[1]);
+	  report_file_error ("Setting file descriptor flags", Qnil);
+	}
+    }
+#endif
+
 #if 0
   /* Replaced by close_process_descs */
   set_exclusive_use (inchannel);
@@ -2150,16 +2166,21 @@ create_process (process, new_argv, current_dir)
 #endif /* SIGCHLD */
 #endif /* !POSIX_SIGNALS */
 
-#if !defined (DONT_REOPEN_PTY)
 	if (pty_flag)
 	  child_setup_tty (xforkout);
-#endif /* not DONT_REOPEN_PTY */
 #ifdef WINDOWSNT
 	pid = child_setup (xforkin, xforkout, xforkout,
 			   new_argv, 1, current_dir);
 #else  /* not WINDOWSNT */
+#ifdef FD_CLOEXEC
+	emacs_close (wait_child_setup[0]);
+#endif
 	child_setup (xforkin, xforkout, xforkout,
 		     new_argv, 1, current_dir);
+#ifdef FD_CLOEXEC
+	emacs_close (wait_child_setup[0]);
+#endif
+	_exit (1);
 #endif /* not WINDOWSNT */
       }
     environ = save_environ;
@@ -2211,6 +2232,21 @@ create_process (process, new_argv, current_dir)
       else
 #endif
 	XPROCESS (process)->tty_name = Qnil;
+
+#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
+      /* Wait for child_setup to complete in case that vfork is
+	 actually defined as fork.  The descriptor wait_child_setup[1]
+	 of a pipe is closed at the child side either by close-on-exec
+	 on successful execvp or by the explicit emacs_close call
+	 before _exit above.  */
+      {
+	char dummy;
+
+	emacs_close (wait_child_setup[1]);
+	emacs_read (wait_child_setup[0], &dummy, 1);
+	emacs_close (wait_child_setup[0]);
+      }
+#endif
     }
 
   /* Restore the signal state whether vfork succeeded or not.









^ permalink raw reply related	[flat|nested] 5+ messages in thread

* bug#554: OSX: with-temp-buffer kills unrelated processes
  2008-07-16 15:27     ` Markus Triska
@ 2008-07-17  1:51       ` YAMAMOTO Mitsuharu
  0 siblings, 0 replies; 5+ messages in thread
From: YAMAMOTO Mitsuharu @ 2008-07-17  1:51 UTC (permalink / raw)
  To: Markus Triska; +Cc: 554

>>>>> On Wed, 16 Jul 2008 17:27:47 +0200, Markus Triska <markus.triska@gmx.at> said:

> YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> writes:
>> OK, close-on-exec seems to be usable for the `fork' case.  How
>> about the patch below?

> Thank you very much; I've tested the following adapted version of
> your patch with the latest CVS trunk of Emacs, and the problem seems
> gone.

Thanks for testing.

Although whether _exit closes file descriptors or not is
implementation-dependent, the current Emacs code seems to assume that
it always does (in its supported platforms).  If so, close before
_exit and the changes to callproc.c in my previous patch can be
removed.  I'll install a simplified one later.

				     YAMAMOTO Mitsuharu
				mituharu@math.s.chiba-u.ac.jp






^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-07-17  1:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-13 17:39 bug#554: OSX: with-temp-buffer kills unrelated processes Markus Triska
2008-07-14 10:26 ` YAMAMOTO Mitsuharu
2008-07-16  9:17   ` YAMAMOTO Mitsuharu
2008-07-16 15:27     ` Markus Triska
2008-07-17  1:51       ` YAMAMOTO Mitsuharu

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).