aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorJoakim Verona2012-12-04 01:46:34 +0100
committerJoakim Verona2012-12-04 01:46:34 +0100
commitd28fde00abbbf26b7c80700b1c9bc18b5079a30e (patch)
tree3bf606901b01f67d6b2eed3998ac6fae9f4518a8 /src/process.c
parentfa8510a9aabe34d367d935b960eab0abbf060e18 (diff)
parentc38a186c2e06e0a351d166c5ef06d7307e145f45 (diff)
downloademacs-d28fde00abbbf26b7c80700b1c9bc18b5079a30e.tar.gz
emacs-d28fde00abbbf26b7c80700b1c9bc18b5079a30e.zip
auto upstream
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c151
1 files changed, 54 insertions, 97 deletions
diff --git a/src/process.c b/src/process.c
index b23f06fd025..27009882c99 100644
--- a/src/process.c
+++ b/src/process.c
@@ -777,10 +777,23 @@ get_process (register Lisp_Object name)
777/* Fdelete_process promises to immediately forget about the process, but in 777/* Fdelete_process promises to immediately forget about the process, but in
778 reality, Emacs needs to remember those processes until they have been 778 reality, Emacs needs to remember those processes until they have been
779 treated by the SIGCHLD handler and waitpid has been invoked on them; 779 treated by the SIGCHLD handler and waitpid has been invoked on them;
780 otherwise they might fill up the kernel's process table. */ 780 otherwise they might fill up the kernel's process table.
781
782 Some processes created by call-process are also put onto this list. */
781static Lisp_Object deleted_pid_list; 783static Lisp_Object deleted_pid_list;
782#endif 784#endif
783 785
786void
787record_deleted_pid (pid_t pid)
788{
789#ifdef SIGCHLD
790 deleted_pid_list = Fcons (make_fixnum_or_float (pid),
791 /* GC treated elements set to nil. */
792 Fdelq (Qnil, deleted_pid_list));
793
794#endif
795}
796
784DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0, 797DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
785 doc: /* Delete PROCESS: kill it and forget about it immediately. 798 doc: /* Delete PROCESS: kill it and forget about it immediately.
786PROCESS may be a process, a buffer, the name of a process or buffer, or 799PROCESS may be a process, a buffer, the name of a process or buffer, or
@@ -807,9 +820,7 @@ nil, indicating the current buffer's process. */)
807 pid_t pid = p->pid; 820 pid_t pid = p->pid;
808 821
809 /* No problem storing the pid here, as it is still in Vprocess_alist. */ 822 /* No problem storing the pid here, as it is still in Vprocess_alist. */
810 deleted_pid_list = Fcons (make_fixnum_or_float (pid), 823 record_deleted_pid (pid);
811 /* GC treated elements set to nil. */
812 Fdelq (Qnil, deleted_pid_list));
813 /* If the process has already signaled, remove it from the list. */ 824 /* If the process has already signaled, remove it from the list. */
814 if (p->raw_status_new) 825 if (p->raw_status_new)
815 update_status (p); 826 update_status (p);
@@ -1586,9 +1597,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1586 volatile int pty_flag = 0; 1597 volatile int pty_flag = 0;
1587 volatile Lisp_Object lisp_pty_name = Qnil; 1598 volatile Lisp_Object lisp_pty_name = Qnil;
1588 volatile Lisp_Object encoded_current_dir; 1599 volatile Lisp_Object encoded_current_dir;
1589#if HAVE_WORKING_VFORK
1590 char **volatile save_environ;
1591#endif
1592 1600
1593 inchannel = outchannel = -1; 1601 inchannel = outchannel = -1;
1594 1602
@@ -1688,12 +1696,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1688 pthread_sigmask (SIG_BLOCK, &blocked, 0); 1696 pthread_sigmask (SIG_BLOCK, &blocked, 0);
1689#endif 1697#endif
1690 1698
1691#if HAVE_WORKING_VFORK
1692 /* child_setup must clobber environ on systems with true vfork.
1693 Protect it from permanent change. */
1694 save_environ = environ;
1695#endif
1696
1697#ifndef WINDOWSNT 1699#ifndef WINDOWSNT
1698 pid = vfork (); 1700 pid = vfork ();
1699 if (pid == 0) 1701 if (pid == 0)
@@ -1819,10 +1821,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1819 1821
1820 /* Back in the parent process. */ 1822 /* Back in the parent process. */
1821 1823
1822#if HAVE_WORKING_VFORK
1823 environ = save_environ;
1824#endif
1825
1826 XPROCESS (process)->pid = pid; 1824 XPROCESS (process)->pid = pid;
1827 if (0 <= pid) 1825 if (0 <= pid)
1828 XPROCESS (process)->alive = 1; 1826 XPROCESS (process)->alive = 1;
@@ -1874,7 +1872,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1874 /* Wait for child_setup to complete in case that vfork is 1872 /* Wait for child_setup to complete in case that vfork is
1875 actually defined as fork. The descriptor wait_child_setup[1] 1873 actually defined as fork. The descriptor wait_child_setup[1]
1876 of a pipe is closed at the child side either by close-on-exec 1874 of a pipe is closed at the child side either by close-on-exec
1877 on successful execvp or the _exit call in child_setup. */ 1875 on successful execve or the _exit call in child_setup. */
1878 { 1876 {
1879 char dummy; 1877 char dummy;
1880 1878
@@ -6160,35 +6158,37 @@ process has been transmitted to the serial port. */)
6160 return process; 6158 return process;
6161} 6159}
6162 6160
6163/* If the status of the process DESIRED has changed, return true and 6161#ifdef SIGCHLD
6164 set *STATUS to its exit status; otherwise, return false.
6165 If HAVE is nonnegative, assume that HAVE = waitpid (HAVE, STATUS, ...)
6166 has already been invoked, and do not invoke waitpid again. */
6167 6162
6168static bool 6163/* The main Emacs thread records child processes in three places:
6169process_status_retrieved (pid_t desired, pid_t have, int *status)
6170{
6171 if (have < 0)
6172 {
6173 /* Invoke waitpid only with a known process ID; do not invoke
6174 waitpid with a nonpositive argument. Otherwise, Emacs might
6175 reap an unwanted process by mistake. For example, invoking
6176 waitpid (-1, ...) can mess up glib by reaping glib's subprocesses,
6177 so that another thread running glib won't find them. */
6178 do
6179 have = waitpid (desired, status, WNOHANG | WUNTRACED);
6180 while (have < 0 && errno == EINTR);
6181 }
6182 6164
6183 return have == desired; 6165 - Vprocess_alist, for asynchronous subprocesses, which are child
6184} 6166 processes visible to Lisp.
6185 6167
6186/* If PID is nonnegative, the child process PID with wait status W has 6168 - deleted_pid_list, for child processes invisible to Lisp,
6187 changed its status; record this and return true. 6169 typically because of delete-process. These are recorded so that
6170 the processes can be reaped when they exit, so that the operating
6171 system's process table is not cluttered by zombies.
6188 6172
6189 If PID is negative, ignore W, and look for known child processes 6173 - the local variable PID in Fcall_process, call_process_cleanup and
6190 of Emacs whose status have changed. For each one found, record its new 6174 call_process_kill, for synchronous subprocesses.
6191 status. 6175 record_unwind_protect is used to make sure this process is not
6176 forgotten: if the user interrupts call-process and the child
6177 process refuses to exit immediately even with two C-g's,
6178 call_process_kill adds PID's contents to deleted_pid_list before
6179 returning.
6180
6181 The main Emacs thread invokes waitpid only on child processes that
6182 it creates and that have not been reaped. This avoid races on
6183 platforms such as GTK, where other threads create their own
6184 subprocesses which the main thread should not reap. For example,
6185 if the main thread attempted to reap an already-reaped child, it
6186 might inadvertently reap a GTK-created process that happened to
6187 have the same process ID. */
6188
6189/* Handle a SIGCHLD signal by looking for known child processes of
6190 Emacs whose status have changed. For each one found, record its
6191 new status.
6192 6192
6193 All we do is change the status; we do not run sentinels or print 6193 All we do is change the status; we do not run sentinels or print
6194 notifications. That is saved for the next time keyboard input is 6194 notifications. That is saved for the next time keyboard input is
@@ -6211,20 +6211,15 @@ process_status_retrieved (pid_t desired, pid_t have, int *status)
6211 ** Malloc WARNING: This should never call malloc either directly or 6211 ** Malloc WARNING: This should never call malloc either directly or
6212 indirectly; if it does, that is a bug */ 6212 indirectly; if it does, that is a bug */
6213 6213
6214void 6214static void
6215record_child_status_change (pid_t pid, int w) 6215handle_child_signal (int sig)
6216{ 6216{
6217#ifdef SIGCHLD
6218
6219 /* Record at most one child only if we already know one child that
6220 has exited. */
6221 bool record_at_most_one_child = 0 <= pid;
6222
6223 Lisp_Object tail; 6217 Lisp_Object tail;
6224 6218
6225 /* Find the process that signaled us, and record its status. */ 6219 /* Find the process that signaled us, and record its status. */
6226 6220
6227 /* The process can have been deleted by Fdelete_process. */ 6221 /* The process can have been deleted by Fdelete_process, or have
6222 been started asynchronously by Fcall_process. */
6228 for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) 6223 for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail))
6229 { 6224 {
6230 bool all_pids_are_fixnums 6225 bool all_pids_are_fixnums
@@ -6238,12 +6233,8 @@ record_child_status_change (pid_t pid, int w)
6238 deleted_pid = XINT (xpid); 6233 deleted_pid = XINT (xpid);
6239 else 6234 else
6240 deleted_pid = XFLOAT_DATA (xpid); 6235 deleted_pid = XFLOAT_DATA (xpid);
6241 if (process_status_retrieved (deleted_pid, pid, &w)) 6236 if (child_status_changed (deleted_pid, 0, 0))
6242 { 6237 XSETCAR (tail, Qnil);
6243 XSETCAR (tail, Qnil);
6244 if (record_at_most_one_child)
6245 return;
6246 }
6247 } 6238 }
6248 } 6239 }
6249 6240
@@ -6252,15 +6243,17 @@ record_child_status_change (pid_t pid, int w)
6252 { 6243 {
6253 Lisp_Object proc = XCDR (XCAR (tail)); 6244 Lisp_Object proc = XCDR (XCAR (tail));
6254 struct Lisp_Process *p = XPROCESS (proc); 6245 struct Lisp_Process *p = XPROCESS (proc);
6255 if (p->alive && process_status_retrieved (p->pid, pid, &w)) 6246 int status;
6247
6248 if (p->alive && child_status_changed (p->pid, &status, WUNTRACED))
6256 { 6249 {
6257 /* Change the status of the process that was found. */ 6250 /* Change the status of the process that was found. */
6258 p->tick = ++process_tick; 6251 p->tick = ++process_tick;
6259 p->raw_status = w; 6252 p->raw_status = status;
6260 p->raw_status_new = 1; 6253 p->raw_status_new = 1;
6261 6254
6262 /* If process has terminated, stop waiting for its output. */ 6255 /* If process has terminated, stop waiting for its output. */
6263 if (WIFSIGNALED (w) || WIFEXITED (w)) 6256 if (WIFSIGNALED (status) || WIFEXITED (status))
6264 { 6257 {
6265 int clear_desc_flag = 0; 6258 int clear_desc_flag = 0;
6266 p->alive = 0; 6259 p->alive = 0;
@@ -6274,44 +6267,8 @@ record_child_status_change (pid_t pid, int w)
6274 FD_CLR (p->infd, &non_keyboard_wait_mask); 6267 FD_CLR (p->infd, &non_keyboard_wait_mask);
6275 } 6268 }
6276 } 6269 }
6277
6278 /* Tell wait_reading_process_output that it needs to wake up and
6279 look around. */
6280 if (input_available_clear_time)
6281 *input_available_clear_time = make_emacs_time (0, 0);
6282
6283 if (record_at_most_one_child)
6284 return;
6285 } 6270 }
6286 } 6271 }
6287
6288 if (0 <= pid)
6289 {
6290 /* The caller successfully waited for a pid but no asynchronous
6291 process was found for it, so this is a synchronous process. */
6292
6293 synch_process_alive = 0;
6294
6295 /* Report the status of the synchronous process. */
6296 if (WIFEXITED (w))
6297 synch_process_retcode = WEXITSTATUS (w);
6298 else if (WIFSIGNALED (w))
6299 synch_process_termsig = WTERMSIG (w);
6300
6301 /* Tell wait_reading_process_output that it needs to wake up and
6302 look around. */
6303 if (input_available_clear_time)
6304 *input_available_clear_time = make_emacs_time (0, 0);
6305 }
6306#endif
6307}
6308
6309#ifdef SIGCHLD
6310
6311static void
6312handle_child_signal (int sig)
6313{
6314 record_child_status_change (-1, 0);
6315} 6272}
6316 6273
6317static void 6274static void