diff options
| author | Philipp Stephani | 2021-01-09 21:17:42 +0100 |
|---|---|---|
| committer | Philipp Stephani | 2021-01-09 21:26:52 +0100 |
| commit | 4cebd2ded01f733957919cea9d10a67101cb7a67 (patch) | |
| tree | 03d6987b9a16f111409d2cda87d4fb413ad350ca /src/callproc.c | |
| parent | ace749f2e3be5b23cf4cd29c702a0e82d4d871c3 (diff) | |
| download | emacs-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.c | 31 |
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 | ||
| 1232 | int | 1244 | int |
| 1233 | emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err, | 1245 | emacs_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); |