aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-08-21 14:27:30 -0700
committerPaul Eggert2013-08-21 14:27:30 -0700
commit4a88129ae4332cbf3833c00f79100610ca2e576d (patch)
tree3cb80a8ec800bd34dd16b6944f87c0325f3ec833 /src
parent6ee6031083c97309e7c10e17a25f466933e46656 (diff)
downloademacs-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')
-rw-r--r--src/ChangeLog8
-rw-r--r--src/callproc.c45
2 files changed, 36 insertions, 17 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index cb552c9d9d5..8983b6abd64 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
12013-08-21 Paul Eggert <eggert@cs.ucla.edu>
2
3 * callproc.c: Fix race that killed background processes (Bug#15144).
4 (call_process): New arg TEMPFILE_INDEX. Callers changed.
5 Record deleted process-id in critical section, not afterwards.
6 Don't mistakenly kill process created by a call-process invocation
7 that discards output and does not wait.
8
12013-08-21 Dmitry Antipov <dmantipov@yandex.ru> 92013-08-21 Dmitry Antipov <dmantipov@yandex.ru>
2 10
3 Fix compilation with GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE 11 Fix compilation with GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE
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
105static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int); 105static 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
257static Lisp_Object 262static Lisp_Object
258call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd) 263call_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.
1030usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */) 1051usage: (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