Attempt to work around macOS vfork bug
Problem reported by YAMAMOTO Mitsuharu in: http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00342.html This is related to the fix for Bug#26397. * src/callproc.c (call_process_cleanup, call_process) [!MSDOS]: Report internal error if wait_for_termination fails. * src/sysdep.c (get_child_status): Return -1 if waitpid is buggy, instead of aborting. (wait_for_termination): Return bool success value. All callers changed.
This commit is contained in:
parent
df9bec3b39
commit
7c951fd518
3 changed files with 24 additions and 16 deletions
|
@ -202,10 +202,11 @@ call_process_cleanup (Lisp_Object buffer)
|
|||
message1 ("Waiting for process to die...(type C-g again to kill it instantly)");
|
||||
|
||||
/* This will quit on C-g. */
|
||||
wait_for_termination (synch_process_pid, 0, 1);
|
||||
|
||||
bool wait_ok = wait_for_termination (synch_process_pid, NULL, true);
|
||||
synch_process_pid = 0;
|
||||
message1 ("Waiting for process to die...done");
|
||||
message1 (wait_ok
|
||||
? "Waiting for process to die...done"
|
||||
: "Waiting for process to die...internal error");
|
||||
}
|
||||
#endif /* !MSDOS */
|
||||
}
|
||||
|
@ -866,9 +867,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
|
|||
make_number (total_read));
|
||||
}
|
||||
|
||||
bool wait_ok = true;
|
||||
#ifndef MSDOS
|
||||
/* Wait for it to terminate, unless it already has. */
|
||||
wait_for_termination (pid, &status, fd0 < 0);
|
||||
wait_ok = wait_for_termination (pid, &status, fd0 < 0);
|
||||
#endif
|
||||
|
||||
/* Don't kill any children that the subprocess may have left behind
|
||||
|
@ -878,6 +880,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
|
|||
SAFE_FREE ();
|
||||
unbind_to (count, Qnil);
|
||||
|
||||
if (!wait_ok)
|
||||
return build_unibyte_string ("internal error");
|
||||
|
||||
if (WIFSIGNALED (status))
|
||||
{
|
||||
const char *signame;
|
||||
|
|
25
src/sysdep.c
25
src/sysdep.c
|
@ -368,8 +368,8 @@ init_baud_rate (int fd)
|
|||
Use waitpid-style OPTIONS when waiting.
|
||||
If INTERRUPTIBLE, this function is interruptible by a signal.
|
||||
|
||||
Return CHILD if successful, 0 if no status is available;
|
||||
the latter is possible only when options & NOHANG. */
|
||||
Return CHILD if successful, 0 if no status is available, and a
|
||||
negative value (setting errno) if waitpid is buggy. */
|
||||
static pid_t
|
||||
get_child_status (pid_t child, int *status, int options, bool interruptible)
|
||||
{
|
||||
|
@ -392,13 +392,14 @@ get_child_status (pid_t child, int *status, int options, bool interruptible)
|
|||
pid = waitpid (child, status, options);
|
||||
if (0 <= pid)
|
||||
break;
|
||||
|
||||
/* Check that CHILD is a child process that has not been reaped,
|
||||
and that STATUS and OPTIONS are valid. Otherwise abort,
|
||||
as continuing after this internal error could cause Emacs to
|
||||
become confused and kill innocent-victim processes. */
|
||||
if (errno != EINTR)
|
||||
emacs_abort ();
|
||||
{
|
||||
/* Most likely, waitpid is buggy and the operating system
|
||||
lost track of the child somehow. Return -1 and let the
|
||||
caller try to figure things out. Possibly the bug could
|
||||
cause Emacs to kill the wrong process. Oh well. */
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
||||
/* If successful and status is requested, tell wait_reading_process_output
|
||||
|
@ -413,11 +414,13 @@ get_child_status (pid_t child, int *status, int options, bool interruptible)
|
|||
CHILD must be a child process that has not been reaped.
|
||||
If STATUS is non-null, store the waitpid-style exit status into *STATUS
|
||||
and tell wait_reading_process_output that it needs to look around.
|
||||
If INTERRUPTIBLE, this function is interruptible by a signal. */
|
||||
void
|
||||
If INTERRUPTIBLE, this function is interruptible by a signal.
|
||||
Return true if successful, false (setting errno) if CHILD cannot be
|
||||
waited for because waitpid is buggy. */
|
||||
bool
|
||||
wait_for_termination (pid_t child, int *status, bool interruptible)
|
||||
{
|
||||
get_child_status (child, status, 0, interruptible);
|
||||
return 0 <= get_child_status (child, status, 0, interruptible);
|
||||
}
|
||||
|
||||
/* Report whether the subprocess with process id CHILD has changed status.
|
||||
|
|
|
@ -56,7 +56,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#endif
|
||||
|
||||
/* Defined in sysdep.c. */
|
||||
extern void wait_for_termination (pid_t, int *, bool);
|
||||
extern bool wait_for_termination (pid_t, int *, bool);
|
||||
extern pid_t child_status_changed (pid_t, int *, int);
|
||||
|
||||
#endif /* EMACS_SYSWAIT_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue