diff options
| author | Paul Eggert | 2013-08-21 14:27:30 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-08-21 14:27:30 -0700 |
| commit | 4a88129ae4332cbf3833c00f79100610ca2e576d (patch) | |
| tree | 3cb80a8ec800bd34dd16b6944f87c0325f3ec833 /src/callproc.c | |
| parent | 6ee6031083c97309e7c10e17a25f466933e46656 (diff) | |
| download | emacs-4a88129ae4332cbf3833c00f79100610ca2e576d.tar.gz emacs-4a88129ae4332cbf3833c00f79100610ca2e576d.zip | |
* callproc.c: Fix race that killed background processes.
(call_process): New arg TEMPFILE_INDEX. Callers changed.
Record deleted process-id in critical section, not afterwards.
Don't mistakenly kill process created by a call-process invocation
that discards output and does not wait.
Fixes: debbugs:15144
Diffstat (limited to 'src/callproc.c')
| -rw-r--r-- | src/callproc.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/src/callproc.c b/src/callproc.c index 2a9162cb5cc..fca4216b5f7 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -102,7 +102,7 @@ enum | |||
| 102 | CALLPROC_FDS | 102 | CALLPROC_FDS |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int); | 105 | static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t); |
| 106 | 106 | ||
| 107 | /* Block SIGCHLD. */ | 107 | /* Block SIGCHLD. */ |
| 108 | 108 | ||
| @@ -248,14 +248,20 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * | |||
| 248 | report_file_error ("Opening process input file", infile); | 248 | report_file_error ("Opening process input file", infile); |
| 249 | record_unwind_protect_int (close_file_unwind, filefd); | 249 | record_unwind_protect_int (close_file_unwind, filefd); |
| 250 | UNGCPRO; | 250 | UNGCPRO; |
| 251 | return unbind_to (count, call_process (nargs, args, filefd)); | 251 | return unbind_to (count, call_process (nargs, args, filefd, -1)); |
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | /* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file. | 254 | /* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file. |
| 255 | |||
| 256 | If TEMPFILE_INDEX is nonnegative, it is the specpdl index of an | ||
| 257 | unwinder that is intended to remove the input temporary file; in | ||
| 258 | this case NARGS must be at least 2 and ARGS[1] is the file's name. | ||
| 259 | |||
| 255 | At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */ | 260 | At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */ |
| 256 | 261 | ||
| 257 | static Lisp_Object | 262 | static Lisp_Object |
| 258 | call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd) | 263 | call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, |
| 264 | ptrdiff_t tempfile_index) | ||
| 259 | { | 265 | { |
| 260 | Lisp_Object buffer, current_dir, path; | 266 | Lisp_Object buffer, current_dir, path; |
| 261 | bool display_p; | 267 | bool display_p; |
| @@ -661,7 +667,22 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd) | |||
| 661 | child_errno = errno; | 667 | child_errno = errno; |
| 662 | 668 | ||
| 663 | if (pid > 0) | 669 | if (pid > 0) |
| 664 | synch_process_pid = pid; | 670 | { |
| 671 | synch_process_pid = pid; | ||
| 672 | |||
| 673 | if (INTEGERP (buffer)) | ||
| 674 | { | ||
| 675 | if (tempfile_index < 0) | ||
| 676 | record_deleted_pid (pid, Qnil); | ||
| 677 | else | ||
| 678 | { | ||
| 679 | eassert (1 < nargs); | ||
| 680 | record_deleted_pid (pid, args[1]); | ||
| 681 | clear_unwind_protect (tempfile_index); | ||
| 682 | } | ||
| 683 | synch_process_pid = 0; | ||
| 684 | } | ||
| 685 | } | ||
| 665 | 686 | ||
| 666 | unblock_child_signal (); | 687 | unblock_child_signal (); |
| 667 | unblock_input (); | 688 | unblock_input (); |
| @@ -1030,7 +1051,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. | |||
| 1030 | usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */) | 1051 | usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */) |
| 1031 | (ptrdiff_t nargs, Lisp_Object *args) | 1052 | (ptrdiff_t nargs, Lisp_Object *args) |
| 1032 | { | 1053 | { |
| 1033 | struct gcpro gcpro1, gcpro2; | 1054 | struct gcpro gcpro1; |
| 1034 | Lisp_Object infile, val; | 1055 | Lisp_Object infile, val; |
| 1035 | ptrdiff_t count = SPECPDL_INDEX (); | 1056 | ptrdiff_t count = SPECPDL_INDEX (); |
| 1036 | Lisp_Object start = args[0]; | 1057 | Lisp_Object start = args[0]; |
| @@ -1061,8 +1082,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r | |||
| 1061 | record_unwind_protect_int (close_file_unwind, fd); | 1082 | record_unwind_protect_int (close_file_unwind, fd); |
| 1062 | } | 1083 | } |
| 1063 | 1084 | ||
| 1064 | val = infile; | 1085 | GCPRO1 (infile); |
| 1065 | GCPRO2 (infile, val); | ||
| 1066 | 1086 | ||
| 1067 | if (nargs > 3 && !NILP (args[3])) | 1087 | if (nargs > 3 && !NILP (args[3])) |
| 1068 | Fdelete_region (start, end); | 1088 | Fdelete_region (start, end); |
| @@ -1079,16 +1099,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r | |||
| 1079 | } | 1099 | } |
| 1080 | args[1] = infile; | 1100 | args[1] = infile; |
| 1081 | 1101 | ||
| 1082 | val = call_process (nargs, args, fd); | 1102 | val = call_process (nargs, args, fd, empty_input ? -1 : count); |
| 1083 | |||
| 1084 | if (!empty_input && 4 < nargs | ||
| 1085 | && (INTEGERP (CONSP (args[4]) ? XCAR (args[4]) : args[4]))) | ||
| 1086 | { | ||
| 1087 | record_deleted_pid (synch_process_pid, infile); | ||
| 1088 | synch_process_pid = 0; | ||
| 1089 | clear_unwind_protect (count); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | RETURN_UNGCPRO (unbind_to (count, val)); | 1103 | RETURN_UNGCPRO (unbind_to (count, val)); |
| 1093 | } | 1104 | } |
| 1094 | 1105 | ||