mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-26 07:11:34 -08:00
Don't unblock SIGCHLD too early.
We first need to register the received process ID so that 'handle_child_signal' checks it. Otherwise we might never call 'waitpid' for these processes, risking deadlock. * src/callproc.c (call_process): * src/process.c (create_process): Don't unblock SIGCHLD before registering the process ID to wait for. * src/callproc.c (emacs_spawn): Accept a signal set from the caller.
This commit is contained in:
parent
ace749f2e3
commit
4cebd2ded0
3 changed files with 31 additions and 14 deletions
|
|
@ -314,6 +314,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
|
|||
#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
|
||||
char *tempfile = NULL;
|
||||
#else
|
||||
sigset_t oldset;
|
||||
pid_t pid = -1;
|
||||
#endif
|
||||
int child_errno;
|
||||
|
|
@ -601,9 +602,12 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
|
|||
|
||||
#ifndef MSDOS
|
||||
|
||||
block_input ();
|
||||
block_child_signal (&oldset);
|
||||
|
||||
child_errno
|
||||
= emacs_spawn (&pid, filefd, fd_output, fd_error, new_argv, env,
|
||||
SSDATA (current_dir), NULL);
|
||||
SSDATA (current_dir), NULL, &oldset);
|
||||
eassert ((child_errno == 0) == (0 < pid));
|
||||
|
||||
if (pid > 0)
|
||||
|
|
@ -624,6 +628,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
|
|||
}
|
||||
}
|
||||
|
||||
unblock_child_signal (&oldset);
|
||||
unblock_input ();
|
||||
|
||||
if (pid < 0)
|
||||
report_file_errno (CHILD_SETUP_ERROR_DESC, Qnil, child_errno);
|
||||
|
||||
|
|
@ -1227,17 +1234,21 @@ child_setup (int in, int out, int err, char **new_argv, char **env,
|
|||
process image file ARGV[0]. Use ENVP for the environment block for
|
||||
the new process. Use CWD as working directory for the new process.
|
||||
If PTY is not NULL, it must be a pseudoterminal device. If PTY is
|
||||
NULL, don't perform any terminal setup. */
|
||||
NULL, don't perform any terminal setup. OLDSET must be a pointer
|
||||
to a signal set initialized by `block_child_signal'. Before
|
||||
calling this function, call `block_input' and `block_child_signal';
|
||||
afterwards, call `unblock_input' and `unblock_child_signal'. Be
|
||||
sure to call `unblock_child_signal' only after registering NEWPID
|
||||
in a list where `handle_child_signal' can find it! */
|
||||
|
||||
int
|
||||
emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
|
||||
char **argv, char **envp, const char *cwd, const char *pty)
|
||||
char **argv, char **envp, const char *cwd,
|
||||
const char *pty, const sigset_t *oldset)
|
||||
{
|
||||
sigset_t oldset;
|
||||
int pid;
|
||||
|
||||
block_input ();
|
||||
block_child_signal (&oldset);
|
||||
eassert (input_blocked_p ());
|
||||
|
||||
#ifndef WINDOWSNT
|
||||
/* vfork, and prevent local vars from being clobbered by the vfork. */
|
||||
|
|
@ -1249,6 +1260,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
|
|||
int volatile stdout_volatile = std_out;
|
||||
int volatile stderr_volatile = std_err;
|
||||
char **volatile envp_volatile = envp;
|
||||
const sigset_t *volatile oldset_volatile = oldset;
|
||||
|
||||
#ifdef DARWIN_OS
|
||||
/* Darwin doesn't let us run setsid after a vfork, so use fork when
|
||||
|
|
@ -1270,6 +1282,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
|
|||
std_out = stdout_volatile;
|
||||
std_err = stderr_volatile;
|
||||
envp = envp_volatile;
|
||||
oldset = oldset_volatile;
|
||||
|
||||
if (pid == 0)
|
||||
#endif /* not WINDOWSNT */
|
||||
|
|
@ -1364,7 +1377,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
|
|||
#endif
|
||||
|
||||
/* Stop blocking SIGCHLD in the child. */
|
||||
unblock_child_signal (&oldset);
|
||||
unblock_child_signal (oldset);
|
||||
|
||||
if (pty_flag)
|
||||
child_setup_tty (std_out);
|
||||
|
|
@ -1382,10 +1395,6 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
|
|||
|
||||
int vfork_error = pid < 0 ? errno : 0;
|
||||
|
||||
/* Stop blocking in the parent. */
|
||||
unblock_child_signal (&oldset);
|
||||
unblock_input ();
|
||||
|
||||
if (pid < 0)
|
||||
{
|
||||
eassert (0 < vfork_error);
|
||||
|
|
|
|||
|
|
@ -4495,8 +4495,8 @@ extern void setup_process_coding_systems (Lisp_Object);
|
|||
# define CHILD_SETUP_ERROR_DESC "Doing vfork"
|
||||
#endif
|
||||
|
||||
extern int emacs_spawn (pid_t *, int, int, int, char **, char **, const char *,
|
||||
const char *);
|
||||
extern int emacs_spawn (pid_t *, int, int, int, char **, char **,
|
||||
const char *, const char *, const sigset_t *);
|
||||
extern char **make_environment_block (Lisp_Object);
|
||||
extern void init_callproc_1 (void);
|
||||
extern void init_callproc (void);
|
||||
|
|
|
|||
|
|
@ -2059,6 +2059,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
|
|||
bool pty_flag = 0;
|
||||
char pty_name[PTY_NAME_SIZE];
|
||||
Lisp_Object lisp_pty_name = Qnil;
|
||||
sigset_t oldset;
|
||||
|
||||
inchannel = outchannel = -1;
|
||||
|
||||
|
|
@ -2139,13 +2140,16 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
|
|||
setup_process_coding_systems (process);
|
||||
char **env = make_environment_block (current_dir);
|
||||
|
||||
block_input ();
|
||||
block_child_signal (&oldset);
|
||||
|
||||
pty_flag = p->pty_flag;
|
||||
eassert (pty_flag == ! NILP (lisp_pty_name));
|
||||
|
||||
vfork_errno
|
||||
= emacs_spawn (&pid, forkin, forkout, forkerr, new_argv, env,
|
||||
SSDATA (current_dir),
|
||||
pty_flag ? SSDATA (lisp_pty_name) : NULL);
|
||||
pty_flag ? SSDATA (lisp_pty_name) : NULL, &oldset);
|
||||
|
||||
eassert ((vfork_errno == 0) == (0 < pid));
|
||||
|
||||
|
|
@ -2153,6 +2157,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
|
|||
if (pid >= 0)
|
||||
p->alive = 1;
|
||||
|
||||
/* Stop blocking in the parent. */
|
||||
unblock_child_signal (&oldset);
|
||||
unblock_input ();
|
||||
|
||||
/* Environment block no longer needed. */
|
||||
unbind_to (count, Qnil);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue