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.
This commit is contained in:
parent
02c66599e3
commit
ee01079735
3 changed files with 25 additions and 38 deletions
|
@ -1,3 +1,13 @@
|
|||
2013-07-21 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
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 <rgm@gnu.org>
|
||||
|
||||
* image.c (Fimage_flush): Fix doc typo.
|
||||
|
|
|
@ -1193,6 +1193,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
|
|||
{
|
||||
char **env;
|
||||
char *pwd_var;
|
||||
int exec_errno;
|
||||
#ifdef WINDOWSNT
|
||||
int cpid;
|
||||
HANDLE handles[3];
|
||||
|
@ -1368,13 +1369,16 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
|
|||
tcsetpgrp (0, pid);
|
||||
|
||||
execve (new_argv[0], new_argv, env);
|
||||
exec_errno = errno;
|
||||
|
||||
/* 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");
|
||||
/* 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);
|
||||
|
||||
_exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
|
||||
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);
|
||||
|
|
|
@ -1599,12 +1599,6 @@ start_process_unwind (Lisp_Object proc)
|
|||
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 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
|
|||
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 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
|
|||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue