diff options
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 215 |
1 files changed, 103 insertions, 112 deletions
diff --git a/src/process.c b/src/process.c index 77e99ead01f..43f0239d301 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -130,6 +130,10 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, | |||
| 130 | EMACS_TIME *, void *); | 130 | EMACS_TIME *, void *); |
| 131 | #endif | 131 | #endif |
| 132 | 132 | ||
| 133 | /* This is for DOS_NT ports. FIXME: Remove this old portability cruft | ||
| 134 | by having DOS_NT ports implement waitpid instead of wait. Nowadays | ||
| 135 | POSIXish hosts all define waitpid, WNOHANG, and WUNTRACED, as these | ||
| 136 | have been standard since POSIX.1-1988. */ | ||
| 133 | #ifndef WNOHANG | 137 | #ifndef WNOHANG |
| 134 | # undef waitpid | 138 | # undef waitpid |
| 135 | # define waitpid(pid, status, options) wait (status) | 139 | # define waitpid(pid, status, options) wait (status) |
| @@ -795,9 +799,8 @@ get_process (register Lisp_Object name) | |||
| 795 | #ifdef SIGCHLD | 799 | #ifdef SIGCHLD |
| 796 | /* Fdelete_process promises to immediately forget about the process, but in | 800 | /* Fdelete_process promises to immediately forget about the process, but in |
| 797 | reality, Emacs needs to remember those processes until they have been | 801 | reality, Emacs needs to remember those processes until they have been |
| 798 | treated by the SIGCHLD handler; otherwise this handler would consider the | 802 | treated by the SIGCHLD handler and waitpid has been invoked on them; |
| 799 | process as being synchronous and say that the synchronous process is | 803 | otherwise they might fill up the kernel's process table. */ |
| 800 | dead. */ | ||
| 801 | static Lisp_Object deleted_pid_list; | 804 | static Lisp_Object deleted_pid_list; |
| 802 | #endif | 805 | #endif |
| 803 | 806 | ||
| @@ -1704,16 +1707,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1704 | if (inchannel > max_process_desc) | 1707 | if (inchannel > max_process_desc) |
| 1705 | max_process_desc = inchannel; | 1708 | max_process_desc = inchannel; |
| 1706 | 1709 | ||
| 1707 | /* Until we store the proper pid, enable the SIGCHLD handler | 1710 | /* This may signal an error. */ |
| 1708 | to recognize an unknown pid as standing for this process. | ||
| 1709 | It is very important not to let this `marker' value stay | ||
| 1710 | in the table after this function has returned; if it does | ||
| 1711 | it might cause call-process to hang and subsequent asynchronous | ||
| 1712 | processes to get their return values scrambled. */ | ||
| 1713 | XPROCESS (process)->pid = -1; | ||
| 1714 | |||
| 1715 | /* This must be called after the above line because it may signal an | ||
| 1716 | error. */ | ||
| 1717 | setup_process_coding_systems (process); | 1711 | setup_process_coding_systems (process); |
| 1718 | 1712 | ||
| 1719 | encoded_current_dir = ENCODE_FILE (current_dir); | 1713 | encoded_current_dir = ENCODE_FILE (current_dir); |
| @@ -1745,7 +1739,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1745 | /* Make the pty be the controlling terminal of the process. */ | 1739 | /* Make the pty be the controlling terminal of the process. */ |
| 1746 | #ifdef HAVE_PTYS | 1740 | #ifdef HAVE_PTYS |
| 1747 | /* First, disconnect its current controlling terminal. */ | 1741 | /* First, disconnect its current controlling terminal. */ |
| 1748 | #ifdef HAVE_SETSID | ||
| 1749 | /* We tried doing setsid only if pty_flag, but it caused | 1742 | /* We tried doing setsid only if pty_flag, but it caused |
| 1750 | process_set_signal to fail on SGI when using a pipe. */ | 1743 | process_set_signal to fail on SGI when using a pipe. */ |
| 1751 | setsid (); | 1744 | setsid (); |
| @@ -1758,12 +1751,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1758 | ioctl (xforkin, TIOCSCTTY, 0); | 1751 | ioctl (xforkin, TIOCSCTTY, 0); |
| 1759 | #endif | 1752 | #endif |
| 1760 | } | 1753 | } |
| 1761 | #else /* not HAVE_SETSID */ | ||
| 1762 | /* It's very important to call setpgid here and no time | ||
| 1763 | afterwards. Otherwise, we lose our controlling tty which | ||
| 1764 | is set when we open the pty. */ | ||
| 1765 | setpgid (0, 0); | ||
| 1766 | #endif /* not HAVE_SETSID */ | ||
| 1767 | #if defined (LDISC1) | 1754 | #if defined (LDISC1) |
| 1768 | if (pty_flag && xforkin >= 0) | 1755 | if (pty_flag && xforkin >= 0) |
| 1769 | { | 1756 | { |
| @@ -1796,22 +1783,15 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1796 | ioctl (j, TIOCNOTTY, 0); | 1783 | ioctl (j, TIOCNOTTY, 0); |
| 1797 | emacs_close (j); | 1784 | emacs_close (j); |
| 1798 | } | 1785 | } |
| 1799 | #ifndef USG | ||
| 1800 | /* In order to get a controlling terminal on some versions | ||
| 1801 | of BSD, it is necessary to put the process in pgrp 0 | ||
| 1802 | before it opens the terminal. */ | ||
| 1803 | setpgid (0, 0); | ||
| 1804 | #endif | ||
| 1805 | } | 1786 | } |
| 1806 | #endif /* TIOCNOTTY */ | 1787 | #endif /* TIOCNOTTY */ |
| 1807 | 1788 | ||
| 1808 | #if !defined (DONT_REOPEN_PTY) | 1789 | #if !defined (DONT_REOPEN_PTY) |
| 1809 | /*** There is a suggestion that this ought to be a | 1790 | /*** There is a suggestion that this ought to be a |
| 1810 | conditional on TIOCSPGRP, | 1791 | conditional on TIOCSPGRP, or !defined TIOCSCTTY. |
| 1811 | or !(defined (HAVE_SETSID) && defined (TIOCSCTTY)). | ||
| 1812 | Trying the latter gave the wrong results on Debian GNU/Linux 1.1; | 1792 | Trying the latter gave the wrong results on Debian GNU/Linux 1.1; |
| 1813 | that system does seem to need this code, even though | 1793 | that system does seem to need this code, even though |
| 1814 | both HAVE_SETSID and TIOCSCTTY are defined. */ | 1794 | both TIOCSCTTY is defined. */ |
| 1815 | /* Now close the pty (if we had it open) and reopen it. | 1795 | /* Now close the pty (if we had it open) and reopen it. |
| 1816 | This makes the pty the controlling terminal of the subprocess. */ | 1796 | This makes the pty the controlling terminal of the subprocess. */ |
| 1817 | if (pty_flag) | 1797 | if (pty_flag) |
| @@ -1880,6 +1860,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1880 | #endif | 1860 | #endif |
| 1881 | 1861 | ||
| 1882 | XPROCESS (process)->pid = pid; | 1862 | XPROCESS (process)->pid = pid; |
| 1863 | if (0 <= pid) | ||
| 1864 | XPROCESS (process)->alive = 1; | ||
| 1883 | 1865 | ||
| 1884 | /* Stop blocking signals in the parent. */ | 1866 | /* Stop blocking signals in the parent. */ |
| 1885 | #ifdef SIGCHLD | 1867 | #ifdef SIGCHLD |
| @@ -4437,7 +4419,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4437 | if (EMACS_TIME_LT (timer_delay, timeout)) | 4419 | if (EMACS_TIME_LT (timer_delay, timeout)) |
| 4438 | { | 4420 | { |
| 4439 | timeout = timer_delay; | 4421 | timeout = timer_delay; |
| 4440 | timeout_reduced_for_timers = 1; | 4422 | timeout_reduced_for_timers = 1; |
| 4441 | } | 4423 | } |
| 4442 | } | 4424 | } |
| 4443 | else | 4425 | else |
| @@ -6273,9 +6255,35 @@ process has been transmitted to the serial port. */) | |||
| 6273 | return process; | 6255 | return process; |
| 6274 | } | 6256 | } |
| 6275 | 6257 | ||
| 6276 | /* On receipt of a signal that a child status has changed, loop asking | 6258 | /* If the status of the process DESIRED has changed, return true and |
| 6277 | about children with changed statuses until the system says there | 6259 | set *STATUS to its exit status; otherwise, return false. |
| 6278 | are no more. | 6260 | If HAVE is nonnegative, assume that HAVE = waitpid (HAVE, STATUS, ...) |
| 6261 | has already been invoked, and do not invoke waitpid again. */ | ||
| 6262 | |||
| 6263 | static bool | ||
| 6264 | process_status_retrieved (pid_t desired, pid_t have, int *status) | ||
| 6265 | { | ||
| 6266 | if (have < 0) | ||
| 6267 | { | ||
| 6268 | /* Invoke waitpid only with a known process ID; do not invoke | ||
| 6269 | waitpid with a nonpositive argument. Otherwise, Emacs might | ||
| 6270 | reap an unwanted process by mistake. For example, invoking | ||
| 6271 | waitpid (-1, ...) can mess up glib by reaping glib's subprocesses, | ||
| 6272 | so that another thread running glib won't find them. */ | ||
| 6273 | do | ||
| 6274 | have = waitpid (desired, status, WNOHANG | WUNTRACED); | ||
| 6275 | while (have < 0 && errno == EINTR); | ||
| 6276 | } | ||
| 6277 | |||
| 6278 | return have == desired; | ||
| 6279 | } | ||
| 6280 | |||
| 6281 | /* If PID is nonnegative, the child process PID with wait status W has | ||
| 6282 | changed its status; record this and return true. | ||
| 6283 | |||
| 6284 | If PID is negative, ignore W, and look for known child processes | ||
| 6285 | of Emacs whose status have changed. For each one found, record its new | ||
| 6286 | status. | ||
| 6279 | 6287 | ||
| 6280 | All we do is change the status; we do not run sentinels or print | 6288 | All we do is change the status; we do not run sentinels or print |
| 6281 | notifications. That is saved for the next time keyboard input is | 6289 | notifications. That is saved for the next time keyboard input is |
| @@ -6298,13 +6306,23 @@ process has been transmitted to the serial port. */) | |||
| 6298 | ** Malloc WARNING: This should never call malloc either directly or | 6306 | ** Malloc WARNING: This should never call malloc either directly or |
| 6299 | indirectly; if it does, that is a bug */ | 6307 | indirectly; if it does, that is a bug */ |
| 6300 | 6308 | ||
| 6301 | /* Record the changed status of the child process PID with wait status W. */ | ||
| 6302 | void | 6309 | void |
| 6303 | record_child_status_change (pid_t pid, int w) | 6310 | record_child_status_change (pid_t pid, int w) |
| 6304 | { | 6311 | { |
| 6305 | #ifdef SIGCHLD | 6312 | #ifdef SIGCHLD |
| 6306 | Lisp_Object proc; | 6313 | |
| 6307 | struct Lisp_Process *p; | 6314 | # ifdef WNOHANG |
| 6315 | /* On POSIXish hosts, record at most one child only if we already | ||
| 6316 | know one child that has exited. */ | ||
| 6317 | bool record_at_most_one_child = 0 <= pid; | ||
| 6318 | # else | ||
| 6319 | /* On DOS_NT (the only porting target that lacks WNOHANG), | ||
| 6320 | record the status of at most one child process, since the SIGCHLD | ||
| 6321 | handler must return right away. If any more processes want to | ||
| 6322 | signal us, we will get another signal. */ | ||
| 6323 | bool record_at_most_one_child = 1; | ||
| 6324 | # endif | ||
| 6325 | |||
| 6308 | Lisp_Object tail; | 6326 | Lisp_Object tail; |
| 6309 | 6327 | ||
| 6310 | /* Find the process that signaled us, and record its status. */ | 6328 | /* Find the process that signaled us, and record its status. */ |
| @@ -6312,68 +6330,69 @@ record_child_status_change (pid_t pid, int w) | |||
| 6312 | /* The process can have been deleted by Fdelete_process. */ | 6330 | /* The process can have been deleted by Fdelete_process. */ |
| 6313 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) | 6331 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) |
| 6314 | { | 6332 | { |
| 6333 | bool all_pids_are_fixnums | ||
| 6334 | = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t) | ||
| 6335 | && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM); | ||
| 6315 | Lisp_Object xpid = XCAR (tail); | 6336 | Lisp_Object xpid = XCAR (tail); |
| 6316 | if ((INTEGERP (xpid) && pid == XINT (xpid)) | 6337 | if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid)) |
| 6317 | || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid))) | ||
| 6318 | { | 6338 | { |
| 6319 | XSETCAR (tail, Qnil); | 6339 | pid_t deleted_pid; |
| 6320 | return; | 6340 | if (INTEGERP (xpid)) |
| 6341 | deleted_pid = XINT (xpid); | ||
| 6342 | else | ||
| 6343 | deleted_pid = XFLOAT_DATA (xpid); | ||
| 6344 | if (process_status_retrieved (deleted_pid, pid, &w)) | ||
| 6345 | { | ||
| 6346 | XSETCAR (tail, Qnil); | ||
| 6347 | if (record_at_most_one_child) | ||
| 6348 | return; | ||
| 6349 | } | ||
| 6321 | } | 6350 | } |
| 6322 | } | 6351 | } |
| 6323 | 6352 | ||
| 6324 | /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ | 6353 | /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ |
| 6325 | p = 0; | ||
| 6326 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | 6354 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) |
| 6327 | { | 6355 | { |
| 6328 | proc = XCDR (XCAR (tail)); | 6356 | Lisp_Object proc = XCDR (XCAR (tail)); |
| 6329 | p = XPROCESS (proc); | 6357 | struct Lisp_Process *p = XPROCESS (proc); |
| 6330 | if (EQ (p->type, Qreal) && p->pid == pid) | 6358 | if (p->alive && process_status_retrieved (p->pid, pid, &w)) |
| 6331 | break; | 6359 | { |
| 6332 | p = 0; | 6360 | /* Change the status of the process that was found. */ |
| 6333 | } | 6361 | p->tick = ++process_tick; |
| 6334 | 6362 | p->raw_status = w; | |
| 6335 | /* Look for an asynchronous process whose pid hasn't been filled | 6363 | p->raw_status_new = 1; |
| 6336 | in yet. */ | ||
| 6337 | if (! p) | ||
| 6338 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6339 | { | ||
| 6340 | proc = XCDR (XCAR (tail)); | ||
| 6341 | p = XPROCESS (proc); | ||
| 6342 | if (p->pid == -1) | ||
| 6343 | break; | ||
| 6344 | p = 0; | ||
| 6345 | } | ||
| 6346 | 6364 | ||
| 6347 | /* Change the status of the process that was found. */ | 6365 | /* If process has terminated, stop waiting for its output. */ |
| 6348 | if (p) | 6366 | if (WIFSIGNALED (w) || WIFEXITED (w)) |
| 6349 | { | 6367 | { |
| 6350 | int clear_desc_flag = 0; | 6368 | int clear_desc_flag = 0; |
| 6369 | p->alive = 0; | ||
| 6370 | if (p->infd >= 0) | ||
| 6371 | clear_desc_flag = 1; | ||
| 6351 | 6372 | ||
| 6352 | p->tick = ++process_tick; | 6373 | /* clear_desc_flag avoids a compiler bug in Microsoft C. */ |
| 6353 | p->raw_status = w; | 6374 | if (clear_desc_flag) |
| 6354 | p->raw_status_new = 1; | 6375 | { |
| 6376 | FD_CLR (p->infd, &input_wait_mask); | ||
| 6377 | FD_CLR (p->infd, &non_keyboard_wait_mask); | ||
| 6378 | } | ||
| 6379 | } | ||
| 6355 | 6380 | ||
| 6356 | /* If process has terminated, stop waiting for its output. */ | 6381 | /* Tell wait_reading_process_output that it needs to wake up and |
| 6357 | if ((WIFSIGNALED (w) || WIFEXITED (w)) | 6382 | look around. */ |
| 6358 | && p->infd >= 0) | 6383 | if (input_available_clear_time) |
| 6359 | clear_desc_flag = 1; | 6384 | *input_available_clear_time = make_emacs_time (0, 0); |
| 6360 | 6385 | ||
| 6361 | /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */ | 6386 | if (record_at_most_one_child) |
| 6362 | if (clear_desc_flag) | 6387 | return; |
| 6363 | { | ||
| 6364 | FD_CLR (p->infd, &input_wait_mask); | ||
| 6365 | FD_CLR (p->infd, &non_keyboard_wait_mask); | ||
| 6366 | } | 6388 | } |
| 6367 | |||
| 6368 | /* Tell wait_reading_process_output that it needs to wake up and | ||
| 6369 | look around. */ | ||
| 6370 | if (input_available_clear_time) | ||
| 6371 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6372 | } | 6389 | } |
| 6373 | /* There was no asynchronous process found for that pid: we have | 6390 | |
| 6374 | a synchronous process. */ | 6391 | if (0 <= pid) |
| 6375 | else | ||
| 6376 | { | 6392 | { |
| 6393 | /* The caller successfully waited for a pid but no asynchronous | ||
| 6394 | process was found for it, so this is a synchronous process. */ | ||
| 6395 | |||
| 6377 | synch_process_alive = 0; | 6396 | synch_process_alive = 0; |
| 6378 | 6397 | ||
| 6379 | /* Report the status of the synchronous process. */ | 6398 | /* Report the status of the synchronous process. */ |
| @@ -6392,38 +6411,10 @@ record_child_status_change (pid_t pid, int w) | |||
| 6392 | 6411 | ||
| 6393 | #ifdef SIGCHLD | 6412 | #ifdef SIGCHLD |
| 6394 | 6413 | ||
| 6395 | /* On some systems, the SIGCHLD handler must return right away. If | ||
| 6396 | any more processes want to signal us, we will get another signal. | ||
| 6397 | Otherwise, loop around to use up all the processes that have | ||
| 6398 | something to tell us. */ | ||
| 6399 | #if (defined WINDOWSNT \ | ||
| 6400 | || (defined USG && !defined GNU_LINUX \ | ||
| 6401 | && !(defined HPUX && defined WNOHANG))) | ||
| 6402 | enum { CAN_HANDLE_MULTIPLE_CHILDREN = 0 }; | ||
| 6403 | #else | ||
| 6404 | enum { CAN_HANDLE_MULTIPLE_CHILDREN = 1 }; | ||
| 6405 | #endif | ||
| 6406 | |||
| 6407 | static void | 6414 | static void |
| 6408 | handle_child_signal (int sig) | 6415 | handle_child_signal (int sig) |
| 6409 | { | 6416 | { |
| 6410 | do | 6417 | record_child_status_change (-1, 0); |
| 6411 | { | ||
| 6412 | pid_t pid; | ||
| 6413 | int status; | ||
| 6414 | |||
| 6415 | do | ||
| 6416 | pid = waitpid (-1, &status, WNOHANG | WUNTRACED); | ||
| 6417 | while (pid < 0 && errno == EINTR); | ||
| 6418 | |||
| 6419 | /* PID == 0 means no processes found, PID == -1 means a real failure. | ||
| 6420 | Either way, we have done all our job. */ | ||
| 6421 | if (pid <= 0) | ||
| 6422 | break; | ||
| 6423 | |||
| 6424 | record_child_status_change (pid, status); | ||
| 6425 | } | ||
| 6426 | while (CAN_HANDLE_MULTIPLE_CHILDREN); | ||
| 6427 | } | 6418 | } |
| 6428 | 6419 | ||
| 6429 | static void | 6420 | static void |