• Paul Eggert's avatar
    Fix a race condition that causes Emacs to mess up glib. · 0b3d4a47
    Paul Eggert authored
    The symptom is a diagnostic "GLib-WARNING **: In call to
    g_spawn_sync(), exit status of a child process was requested but
    SIGCHLD action was set to SIG_IGN and ECHILD was received by
    waitpid(), so exit status can't be returned."  The diagnostic
    is partly wrong, as the SIGCHLD action is not set to SIG_IGN.
    The real bug is a race condition between Emacs and glib: Emacs
    does a waitpid (-1, ...) and reaps glib's subprocess by mistake,
    so that glib can't find it.  Work around the bug by invoking
    waitpid only on subprocesses that Emacs itself creates.
    * process.c (create_process, record_child_status_change):
    Don't use special value -1 in pid field, as the caller now must
    know the pid rather than having the callee infer it.  The
    inference was sometimes incorrect anyway, due to another race.
    (create_process): Set new 'alive' member if child is created.
    (process_status_retrieved): New function.
    (record_child_status_change): Use it.
    Accept negative 1st argument, which means to wait for the
    processes that Emacs already knows about.  Move special-case code
    for DOS_NT (which lacks WNOHANG) here, from caller.  Keep track of
    processes that have already been waited for, by testing and
    clearing new 'alive' member.
    (CAN_HANDLE_MULTIPLE_CHILDREN): Remove, as record_child_status_change
    now does this internally.
    (handle_child_signal): Let record_child_status_change do all
    the work, since we do not want to reap all exited child processes,
    only the child processes that Emacs itself created.
    * process.h (Lisp_Process): New boolean member 'alive'.
    Fixes: debbugs:8855
ChangeLog 760 KB