diff options
| author | Joakim Verona | 2012-12-06 08:40:20 +0100 |
|---|---|---|
| committer | Joakim Verona | 2012-12-06 08:40:20 +0100 |
| commit | 6b946658438570898db449b70906d63c00da21ce (patch) | |
| tree | a811b15dc1f4ecbc517e4f1c049d980b4fb36f0d /src | |
| parent | ec51343a4e6490c45db57418747c247354b9b6e9 (diff) | |
| parent | 7fc5e83f7fa6e060596204b1c1cd9a7890de7a66 (diff) | |
| download | emacs-6b946658438570898db449b70906d63c00da21ce.tar.gz emacs-6b946658438570898db449b70906d63c00da21ce.zip | |
auto upstream
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 10 | ||||
| -rw-r--r-- | src/callproc.c | 30 | ||||
| -rw-r--r-- | src/process.c | 36 | ||||
| -rw-r--r-- | src/process.h | 6 |
4 files changed, 53 insertions, 29 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index d9e566eae69..542b2c0174a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | 2012-12-06 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Fix a recently-introduced delete-process race condition. | ||
| 4 | * callproc.c, process.h (record_kill_process): | ||
| 5 | New function, containing part of the old call_process_kill. | ||
| 6 | (call_process_kill): Use it. | ||
| 7 | This does not change call_process_kill's behavior. | ||
| 8 | * process.c (Fdelete_process): Use record_kill_process to fix a | ||
| 9 | race condition that could cause Emacs to lose track of a child. | ||
| 10 | |||
| 1 | 2012-12-06 Dmitry Antipov <dmantipov@yandex.ru> | 11 | 2012-12-06 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 12 | ||
| 3 | Avoid code duplication between prev_frame and next_frame. | 13 | Avoid code duplication between prev_frame and next_frame. |
diff --git a/src/callproc.c b/src/callproc.c index 6153bc1b6c6..e0528a791ea 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -105,6 +105,25 @@ unblock_child_signal (void) | |||
| 105 | #endif | 105 | #endif |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /* If P is reapable, record it as a deleted process and kill it. | ||
| 109 | Do this in a critical section. Unless PID is wedged it will be | ||
| 110 | reaped on receipt of the first SIGCHLD after the critical section. */ | ||
| 111 | |||
| 112 | void | ||
| 113 | record_kill_process (struct Lisp_Process *p) | ||
| 114 | { | ||
| 115 | block_child_signal (); | ||
| 116 | |||
| 117 | if (p->alive) | ||
| 118 | { | ||
| 119 | p->alive = 0; | ||
| 120 | record_deleted_pid (p->pid); | ||
| 121 | EMACS_KILLPG (p->pid, SIGKILL); | ||
| 122 | } | ||
| 123 | |||
| 124 | unblock_child_signal (); | ||
| 125 | } | ||
| 126 | |||
| 108 | /* Clean up when exiting call_process_cleanup. */ | 127 | /* Clean up when exiting call_process_cleanup. */ |
| 109 | 128 | ||
| 110 | static Lisp_Object | 129 | static Lisp_Object |
| @@ -113,15 +132,12 @@ call_process_kill (Lisp_Object ignored) | |||
| 113 | if (0 <= synch_process_fd) | 132 | if (0 <= synch_process_fd) |
| 114 | emacs_close (synch_process_fd); | 133 | emacs_close (synch_process_fd); |
| 115 | 134 | ||
| 116 | /* If PID is reapable, kill it and record it as a deleted process. | ||
| 117 | Do this in a critical section. Unless PID is wedged it will be | ||
| 118 | reaped on receipt of the first SIGCHLD after the critical section. */ | ||
| 119 | if (synch_process_pid) | 135 | if (synch_process_pid) |
| 120 | { | 136 | { |
| 121 | block_child_signal (); | 137 | struct Lisp_Process proc; |
| 122 | record_deleted_pid (synch_process_pid); | 138 | proc.alive = 1; |
| 123 | EMACS_KILLPG (synch_process_pid, SIGKILL); | 139 | proc.pid = synch_process_pid; |
| 124 | unblock_child_signal (); | 140 | record_kill_process (&proc); |
| 125 | } | 141 | } |
| 126 | 142 | ||
| 127 | return Qnil; | 143 | return Qnil; |
diff --git a/src/process.c b/src/process.c index 27009882c99..007a07942e6 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -813,30 +813,22 @@ nil, indicating the current buffer's process. */) | |||
| 813 | status_notify (p); | 813 | status_notify (p); |
| 814 | redisplay_preserve_echo_area (13); | 814 | redisplay_preserve_echo_area (13); |
| 815 | } | 815 | } |
| 816 | else if (p->infd >= 0) | 816 | else |
| 817 | { | 817 | { |
| 818 | #ifdef SIGCHLD | 818 | if (p->alive) |
| 819 | Lisp_Object symbol; | 819 | record_kill_process (p); |
| 820 | pid_t pid = p->pid; | 820 | |
| 821 | 821 | if (p->infd >= 0) | |
| 822 | /* No problem storing the pid here, as it is still in Vprocess_alist. */ | ||
| 823 | record_deleted_pid (pid); | ||
| 824 | /* If the process has already signaled, remove it from the list. */ | ||
| 825 | if (p->raw_status_new) | ||
| 826 | update_status (p); | ||
| 827 | symbol = p->status; | ||
| 828 | if (CONSP (p->status)) | ||
| 829 | symbol = XCAR (p->status); | ||
| 830 | if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)) | ||
| 831 | deleted_pid_list | ||
| 832 | = Fdelete (make_fixnum_or_float (pid), deleted_pid_list); | ||
| 833 | else | ||
| 834 | #endif | ||
| 835 | { | 822 | { |
| 836 | Fkill_process (process, Qnil); | 823 | /* Update P's status, since record_kill_process will make the |
| 837 | /* Do this now, since remove_process will make the | 824 | SIGCHLD handler update deleted_pid_list, not *P. */ |
| 838 | SIGCHLD handler do nothing. */ | 825 | Lisp_Object symbol; |
| 839 | pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil))); | 826 | if (p->raw_status_new) |
| 827 | update_status (p); | ||
| 828 | symbol = CONSP (p->status) ? XCAR (p->status) : p->status; | ||
| 829 | if (! (EQ (symbol, Qsignal) || EQ (symbol, Qexit))) | ||
| 830 | pset_status (p, list2 (Qsignal, make_number (SIGKILL))); | ||
| 831 | |||
| 840 | p->tick = ++process_tick; | 832 | p->tick = ++process_tick; |
| 841 | status_notify (p); | 833 | status_notify (p); |
| 842 | redisplay_preserve_echo_area (13); | 834 | redisplay_preserve_echo_area (13); |
diff --git a/src/process.h b/src/process.h index 4fa22747ca9..a0521689abf 100644 --- a/src/process.h +++ b/src/process.h | |||
| @@ -198,6 +198,12 @@ extern Lisp_Object QCspeed; | |||
| 198 | extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven; | 198 | extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven; |
| 199 | extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary; | 199 | extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary; |
| 200 | 200 | ||
| 201 | /* Defined in callproc.c. */ | ||
| 202 | |||
| 203 | extern void record_kill_process (struct Lisp_Process *); | ||
| 204 | |||
| 205 | /* Defined in process.c. */ | ||
| 206 | |||
| 201 | extern Lisp_Object list_system_processes (void); | 207 | extern Lisp_Object list_system_processes (void); |
| 202 | extern Lisp_Object system_process_attributes (Lisp_Object); | 208 | extern Lisp_Object system_process_attributes (Lisp_Object); |
| 203 | 209 | ||