diff options
| author | Paul Eggert | 2012-12-05 23:31:58 -0800 |
|---|---|---|
| committer | Paul Eggert | 2012-12-05 23:31:58 -0800 |
| commit | 35fb8050457a0edc6a09f38fb1dd84a9c7732352 (patch) | |
| tree | 563dbd821a3efc83e6ad71c7f6a0dc21f26c8c5b /src/process.c | |
| parent | 565212e5983cdcc478ed34bcdbd63f154e5e418f (diff) | |
| download | emacs-35fb8050457a0edc6a09f38fb1dd84a9c7732352.tar.gz emacs-35fb8050457a0edc6a09f38fb1dd84a9c7732352.zip | |
Fix a recently-introduced delete-process race condition.
* callproc.c, process.h (record_kill_process):
New function, containing part of the old call_process_kill.
(call_process_kill): Use it.
This does not change call_process_kill's behavior.
* process.c (Fdelete_process): Use record_kill_process to fix a
race condition that could cause Emacs to lose track of a child.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 36 |
1 files changed, 14 insertions, 22 deletions
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); |