aboutsummaryrefslogtreecommitdiffstats
path: root/src/callproc.c
diff options
context:
space:
mode:
authorPhilipp Stephani2021-01-09 21:17:42 +0100
committerPhilipp Stephani2021-01-09 21:26:52 +0100
commit4cebd2ded01f733957919cea9d10a67101cb7a67 (patch)
tree03d6987b9a16f111409d2cda87d4fb413ad350ca /src/callproc.c
parentace749f2e3be5b23cf4cd29c702a0e82d4d871c3 (diff)
downloademacs-4cebd2ded01f733957919cea9d10a67101cb7a67.tar.gz
emacs-4cebd2ded01f733957919cea9d10a67101cb7a67.zip
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.
Diffstat (limited to 'src/callproc.c')
-rw-r--r--src/callproc.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/src/callproc.c b/src/callproc.c
index 8d2a5619eb8..1da315bef18 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -314,6 +314,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
314#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */ 314#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
315 char *tempfile = NULL; 315 char *tempfile = NULL;
316#else 316#else
317 sigset_t oldset;
317 pid_t pid = -1; 318 pid_t pid = -1;
318#endif 319#endif
319 int child_errno; 320 int child_errno;
@@ -601,9 +602,12 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
601 602
602#ifndef MSDOS 603#ifndef MSDOS
603 604
605 block_input ();
606 block_child_signal (&oldset);
607
604 child_errno 608 child_errno
605 = emacs_spawn (&pid, filefd, fd_output, fd_error, new_argv, env, 609 = emacs_spawn (&pid, filefd, fd_output, fd_error, new_argv, env,
606 SSDATA (current_dir), NULL); 610 SSDATA (current_dir), NULL, &oldset);
607 eassert ((child_errno == 0) == (0 < pid)); 611 eassert ((child_errno == 0) == (0 < pid));
608 612
609 if (pid > 0) 613 if (pid > 0)
@@ -624,6 +628,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
624 } 628 }
625 } 629 }
626 630
631 unblock_child_signal (&oldset);
632 unblock_input ();
633
627 if (pid < 0) 634 if (pid < 0)
628 report_file_errno (CHILD_SETUP_ERROR_DESC, Qnil, child_errno); 635 report_file_errno (CHILD_SETUP_ERROR_DESC, Qnil, child_errno);
629 636
@@ -1227,17 +1234,21 @@ child_setup (int in, int out, int err, char **new_argv, char **env,
1227 process image file ARGV[0]. Use ENVP for the environment block for 1234 process image file ARGV[0]. Use ENVP for the environment block for
1228 the new process. Use CWD as working directory for the new process. 1235 the new process. Use CWD as working directory for the new process.
1229 If PTY is not NULL, it must be a pseudoterminal device. If PTY is 1236 If PTY is not NULL, it must be a pseudoterminal device. If PTY is
1230 NULL, don't perform any terminal setup. */ 1237 NULL, don't perform any terminal setup. OLDSET must be a pointer
1238 to a signal set initialized by `block_child_signal'. Before
1239 calling this function, call `block_input' and `block_child_signal';
1240 afterwards, call `unblock_input' and `unblock_child_signal'. Be
1241 sure to call `unblock_child_signal' only after registering NEWPID
1242 in a list where `handle_child_signal' can find it! */
1231 1243
1232int 1244int
1233emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err, 1245emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1234 char **argv, char **envp, const char *cwd, const char *pty) 1246 char **argv, char **envp, const char *cwd,
1247 const char *pty, const sigset_t *oldset)
1235{ 1248{
1236 sigset_t oldset;
1237 int pid; 1249 int pid;
1238 1250
1239 block_input (); 1251 eassert (input_blocked_p ());
1240 block_child_signal (&oldset);
1241 1252
1242#ifndef WINDOWSNT 1253#ifndef WINDOWSNT
1243 /* vfork, and prevent local vars from being clobbered by the vfork. */ 1254 /* 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,
1249 int volatile stdout_volatile = std_out; 1260 int volatile stdout_volatile = std_out;
1250 int volatile stderr_volatile = std_err; 1261 int volatile stderr_volatile = std_err;
1251 char **volatile envp_volatile = envp; 1262 char **volatile envp_volatile = envp;
1263 const sigset_t *volatile oldset_volatile = oldset;
1252 1264
1253#ifdef DARWIN_OS 1265#ifdef DARWIN_OS
1254 /* Darwin doesn't let us run setsid after a vfork, so use fork when 1266 /* 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,
1270 std_out = stdout_volatile; 1282 std_out = stdout_volatile;
1271 std_err = stderr_volatile; 1283 std_err = stderr_volatile;
1272 envp = envp_volatile; 1284 envp = envp_volatile;
1285 oldset = oldset_volatile;
1273 1286
1274 if (pid == 0) 1287 if (pid == 0)
1275#endif /* not WINDOWSNT */ 1288#endif /* not WINDOWSNT */
@@ -1364,7 +1377,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1364#endif 1377#endif
1365 1378
1366 /* Stop blocking SIGCHLD in the child. */ 1379 /* Stop blocking SIGCHLD in the child. */
1367 unblock_child_signal (&oldset); 1380 unblock_child_signal (oldset);
1368 1381
1369 if (pty_flag) 1382 if (pty_flag)
1370 child_setup_tty (std_out); 1383 child_setup_tty (std_out);
@@ -1382,10 +1395,6 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1382 1395
1383 int vfork_error = pid < 0 ? errno : 0; 1396 int vfork_error = pid < 0 ? errno : 0;
1384 1397
1385 /* Stop blocking in the parent. */
1386 unblock_child_signal (&oldset);
1387 unblock_input ();
1388
1389 if (pid < 0) 1398 if (pid < 0)
1390 { 1399 {
1391 eassert (0 < vfork_error); 1400 eassert (0 < vfork_error);