diff options
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 399 |
1 files changed, 182 insertions, 217 deletions
diff --git a/src/process.c b/src/process.c index b45ba733636..6f48463b85b 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -23,15 +23,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 23 | 23 | ||
| 24 | #define PROCESS_INLINE EXTERN_INLINE | 24 | #define PROCESS_INLINE EXTERN_INLINE |
| 25 | 25 | ||
| 26 | #include <signal.h> | ||
| 27 | #include <stdio.h> | 26 | #include <stdio.h> |
| 28 | #include <errno.h> | 27 | #include <errno.h> |
| 29 | #include <setjmp.h> | ||
| 30 | #include <sys/types.h> /* Some typedefs are used in sys/file.h. */ | 28 | #include <sys/types.h> /* Some typedefs are used in sys/file.h. */ |
| 31 | #include <sys/file.h> | 29 | #include <sys/file.h> |
| 32 | #include <sys/stat.h> | 30 | #include <sys/stat.h> |
| 33 | #include <setjmp.h> | ||
| 34 | |||
| 35 | #include <unistd.h> | 31 | #include <unistd.h> |
| 36 | #include <fcntl.h> | 32 | #include <fcntl.h> |
| 37 | 33 | ||
| @@ -76,6 +72,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 76 | #include <bsdtty.h> | 72 | #include <bsdtty.h> |
| 77 | #endif | 73 | #endif |
| 78 | 74 | ||
| 75 | #ifdef USG5_4 | ||
| 76 | # include <sys/stream.h> | ||
| 77 | # include <sys/stropts.h> | ||
| 78 | #endif | ||
| 79 | |||
| 79 | #ifdef HAVE_RES_INIT | 80 | #ifdef HAVE_RES_INIT |
| 80 | #include <netinet/in.h> | 81 | #include <netinet/in.h> |
| 81 | #include <arpa/nameser.h> | 82 | #include <arpa/nameser.h> |
| @@ -124,6 +125,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 124 | #include "xgselect.h" | 125 | #include "xgselect.h" |
| 125 | #endif | 126 | #endif |
| 126 | 127 | ||
| 128 | #ifndef WNOHANG | ||
| 129 | # undef waitpid | ||
| 130 | # define waitpid(pid, status, options) wait (status) | ||
| 131 | #endif | ||
| 132 | #ifndef WUNTRACED | ||
| 133 | # define WUNTRACED 0 | ||
| 134 | #endif | ||
| 135 | |||
| 127 | /* Work around GCC 4.7.0 bug with strict overflow checking; see | 136 | /* Work around GCC 4.7.0 bug with strict overflow checking; see |
| 128 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. | 137 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. |
| 129 | These lines can be removed once the GCC bug is fixed. */ | 138 | These lines can be removed once the GCC bug is fixed. */ |
| @@ -165,16 +174,6 @@ static Lisp_Object QClocal, QCremote, QCcoding; | |||
| 165 | static Lisp_Object QCserver, QCnowait, QCnoquery, QCstop; | 174 | static Lisp_Object QCserver, QCnowait, QCnoquery, QCstop; |
| 166 | static Lisp_Object QCsentinel, QClog, QCoptions, QCplist; | 175 | static Lisp_Object QCsentinel, QClog, QCoptions, QCplist; |
| 167 | static Lisp_Object Qlast_nonmenu_event; | 176 | static Lisp_Object Qlast_nonmenu_event; |
| 168 | /* QCfamily is declared and initialized in xfaces.c, | ||
| 169 | QCfilter in keyboard.c. */ | ||
| 170 | extern Lisp_Object QCfamily, QCfilter; | ||
| 171 | |||
| 172 | /* Qexit is declared and initialized in eval.c. */ | ||
| 173 | |||
| 174 | /* QCfamily is defined in xfaces.c. */ | ||
| 175 | extern Lisp_Object QCfamily; | ||
| 176 | /* QCfilter is defined in keyboard.c. */ | ||
| 177 | extern Lisp_Object QCfilter; | ||
| 178 | 177 | ||
| 179 | #define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork)) | 178 | #define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork)) |
| 180 | #define NETCONN1_P(p) (EQ (p->type, Qnetwork)) | 179 | #define NETCONN1_P(p) (EQ (p->type, Qnetwork)) |
| @@ -215,17 +214,13 @@ static EMACS_INT update_tick; | |||
| 215 | "non-destructive" select. So we require either native select, | 214 | "non-destructive" select. So we require either native select, |
| 216 | or emulation of select using FIONREAD. */ | 215 | or emulation of select using FIONREAD. */ |
| 217 | 216 | ||
| 218 | #ifdef BROKEN_DATAGRAM_SOCKETS | 217 | #ifndef BROKEN_DATAGRAM_SOCKETS |
| 219 | #undef DATAGRAM_SOCKETS | 218 | # if defined HAVE_SELECT || defined USABLE_FIONREAD |
| 220 | #else | 219 | # if defined HAVE_SENDTO && defined HAVE_RECVFROM && defined EMSGSIZE |
| 221 | #ifndef DATAGRAM_SOCKETS | 220 | # define DATAGRAM_SOCKETS |
| 222 | #if defined (HAVE_SELECT) || defined (FIONREAD) | 221 | # endif |
| 223 | #if defined (HAVE_SENDTO) && defined (HAVE_RECVFROM) && defined (EMSGSIZE) | 222 | # endif |
| 224 | #define DATAGRAM_SOCKETS | 223 | #endif |
| 225 | #endif /* HAVE_SENDTO && HAVE_RECVFROM && EMSGSIZE */ | ||
| 226 | #endif /* HAVE_SELECT || FIONREAD */ | ||
| 227 | #endif /* DATAGRAM_SOCKETS */ | ||
| 228 | #endif /* BROKEN_DATAGRAM_SOCKETS */ | ||
| 229 | 224 | ||
| 230 | #if defined HAVE_LOCAL_SOCKETS && defined DATAGRAM_SOCKETS | 225 | #if defined HAVE_LOCAL_SOCKETS && defined DATAGRAM_SOCKETS |
| 231 | # define HAVE_SEQPACKET | 226 | # define HAVE_SEQPACKET |
| @@ -254,7 +249,7 @@ static int process_output_skip; | |||
| 254 | #endif | 249 | #endif |
| 255 | 250 | ||
| 256 | static void create_process (Lisp_Object, char **, Lisp_Object); | 251 | static void create_process (Lisp_Object, char **, Lisp_Object); |
| 257 | #ifdef SIGIO | 252 | #ifdef USABLE_SIGIO |
| 258 | static int keyboard_bit_set (SELECT_TYPE *); | 253 | static int keyboard_bit_set (SELECT_TYPE *); |
| 259 | #endif | 254 | #endif |
| 260 | static void deactivate_process (Lisp_Object); | 255 | static void deactivate_process (Lisp_Object); |
| @@ -811,7 +806,7 @@ get_process (register Lisp_Object name) | |||
| 811 | #ifdef SIGCHLD | 806 | #ifdef SIGCHLD |
| 812 | /* Fdelete_process promises to immediately forget about the process, but in | 807 | /* Fdelete_process promises to immediately forget about the process, but in |
| 813 | reality, Emacs needs to remember those processes until they have been | 808 | reality, Emacs needs to remember those processes until they have been |
| 814 | treated by sigchld_handler; otherwise this handler would consider the | 809 | treated by the SIGCHLD handler; otherwise this handler would consider the |
| 815 | process as being synchronous and say that the synchronous process is | 810 | process as being synchronous and say that the synchronous process is |
| 816 | dead. */ | 811 | dead. */ |
| 817 | static Lisp_Object deleted_pid_list; | 812 | static Lisp_Object deleted_pid_list; |
| @@ -859,7 +854,8 @@ nil, indicating the current buffer's process. */) | |||
| 859 | #endif | 854 | #endif |
| 860 | { | 855 | { |
| 861 | Fkill_process (process, Qnil); | 856 | Fkill_process (process, Qnil); |
| 862 | /* Do this now, since remove_process will make sigchld_handler do nothing. */ | 857 | /* Do this now, since remove_process will make the |
| 858 | SIGCHLD handler do nothing. */ | ||
| 863 | pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil))); | 859 | pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil))); |
| 864 | p->tick = ++process_tick; | 860 | p->tick = ++process_tick; |
| 865 | status_notify (p); | 861 | status_notify (p); |
| @@ -1587,7 +1583,7 @@ static Lisp_Object | |||
| 1587 | start_process_unwind (Lisp_Object proc) | 1583 | start_process_unwind (Lisp_Object proc) |
| 1588 | { | 1584 | { |
| 1589 | if (!PROCESSP (proc)) | 1585 | if (!PROCESSP (proc)) |
| 1590 | abort (); | 1586 | emacs_abort (); |
| 1591 | 1587 | ||
| 1592 | /* Was PROC started successfully? | 1588 | /* Was PROC started successfully? |
| 1593 | -2 is used for a pty with no process, eg for gdb. */ | 1589 | -2 is used for a pty with no process, eg for gdb. */ |
| @@ -1613,15 +1609,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1613 | #if !defined (WINDOWSNT) && defined (FD_CLOEXEC) | 1609 | #if !defined (WINDOWSNT) && defined (FD_CLOEXEC) |
| 1614 | int wait_child_setup[2]; | 1610 | int wait_child_setup[2]; |
| 1615 | #endif | 1611 | #endif |
| 1616 | sigset_t procmask; | 1612 | #ifdef SIGCHLD |
| 1617 | sigset_t blocked; | 1613 | sigset_t blocked, procmask; |
| 1618 | struct sigaction sigint_action; | ||
| 1619 | struct sigaction sigquit_action; | ||
| 1620 | struct sigaction sigpipe_action; | ||
| 1621 | #ifdef AIX | ||
| 1622 | struct sigaction sighup_action; | ||
| 1623 | #endif | 1614 | #endif |
| 1624 | /* Use volatile to protect variables from being clobbered by longjmp. */ | 1615 | /* Use volatile to protect variables from being clobbered by vfork. */ |
| 1625 | volatile int forkin, forkout; | 1616 | volatile int forkin, forkout; |
| 1626 | volatile int pty_flag = 0; | 1617 | volatile int pty_flag = 0; |
| 1627 | 1618 | ||
| @@ -1713,32 +1704,20 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1713 | XPROCESS (process)->pty_flag = pty_flag; | 1704 | XPROCESS (process)->pty_flag = pty_flag; |
| 1714 | pset_status (XPROCESS (process), Qrun); | 1705 | pset_status (XPROCESS (process), Qrun); |
| 1715 | 1706 | ||
| 1707 | #ifdef SIGCHLD | ||
| 1716 | /* Delay interrupts until we have a chance to store | 1708 | /* Delay interrupts until we have a chance to store |
| 1717 | the new fork's pid in its process structure */ | 1709 | the new fork's pid in its process structure */ |
| 1718 | sigemptyset (&blocked); | 1710 | sigemptyset (&blocked); |
| 1719 | #ifdef SIGCHLD | ||
| 1720 | sigaddset (&blocked, SIGCHLD); | 1711 | sigaddset (&blocked, SIGCHLD); |
| 1721 | #endif | ||
| 1722 | #ifdef HAVE_WORKING_VFORK | ||
| 1723 | /* On many hosts (e.g. Solaris 2.4), if a vforked child calls `signal', | ||
| 1724 | this sets the parent's signal handlers as well as the child's. | ||
| 1725 | So delay all interrupts whose handlers the child might munge, | ||
| 1726 | and record the current handlers so they can be restored later. */ | ||
| 1727 | sigaddset (&blocked, SIGINT ); sigaction (SIGINT , 0, &sigint_action ); | ||
| 1728 | sigaddset (&blocked, SIGQUIT); sigaction (SIGQUIT, 0, &sigquit_action); | ||
| 1729 | sigaddset (&blocked, SIGPIPE); sigaction (SIGPIPE, 0, &sigpipe_action); | ||
| 1730 | #ifdef AIX | ||
| 1731 | sigaddset (&blocked, SIGHUP ); sigaction (SIGHUP , 0, &sighup_action ); | ||
| 1732 | #endif | ||
| 1733 | #endif /* HAVE_WORKING_VFORK */ | ||
| 1734 | pthread_sigmask (SIG_BLOCK, &blocked, &procmask); | 1712 | pthread_sigmask (SIG_BLOCK, &blocked, &procmask); |
| 1713 | #endif | ||
| 1735 | 1714 | ||
| 1736 | FD_SET (inchannel, &input_wait_mask); | 1715 | FD_SET (inchannel, &input_wait_mask); |
| 1737 | FD_SET (inchannel, &non_keyboard_wait_mask); | 1716 | FD_SET (inchannel, &non_keyboard_wait_mask); |
| 1738 | if (inchannel > max_process_desc) | 1717 | if (inchannel > max_process_desc) |
| 1739 | max_process_desc = inchannel; | 1718 | max_process_desc = inchannel; |
| 1740 | 1719 | ||
| 1741 | /* Until we store the proper pid, enable sigchld_handler | 1720 | /* Until we store the proper pid, enable the SIGCHLD handler |
| 1742 | to recognize an unknown pid as standing for this process. | 1721 | to recognize an unknown pid as standing for this process. |
| 1743 | It is very important not to let this `marker' value stay | 1722 | It is very important not to let this `marker' value stay |
| 1744 | in the table after this function has returned; if it does | 1723 | in the table after this function has returned; if it does |
| @@ -1766,12 +1745,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1766 | int xforkin = forkin; | 1745 | int xforkin = forkin; |
| 1767 | int xforkout = forkout; | 1746 | int xforkout = forkout; |
| 1768 | 1747 | ||
| 1769 | #if 0 /* This was probably a mistake--it duplicates code later on, | ||
| 1770 | but fails to handle all the cases. */ | ||
| 1771 | /* Make sure SIGCHLD is not blocked in the child. */ | ||
| 1772 | sigsetmask (SIGEMPTYMASK); | ||
| 1773 | #endif | ||
| 1774 | |||
| 1775 | /* Make the pty be the controlling terminal of the process. */ | 1748 | /* Make the pty be the controlling terminal of the process. */ |
| 1776 | #ifdef HAVE_PTYS | 1749 | #ifdef HAVE_PTYS |
| 1777 | /* First, disconnect its current controlling terminal. */ | 1750 | /* First, disconnect its current controlling terminal. */ |
| @@ -1890,8 +1863,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1890 | in the child. */ | 1863 | in the child. */ |
| 1891 | signal (SIGPIPE, SIG_DFL); | 1864 | signal (SIGPIPE, SIG_DFL); |
| 1892 | 1865 | ||
| 1866 | #ifdef SIGCHLD | ||
| 1893 | /* Stop blocking signals in the child. */ | 1867 | /* Stop blocking signals in the child. */ |
| 1894 | pthread_sigmask (SIG_SETMASK, &procmask, 0); | 1868 | pthread_sigmask (SIG_SETMASK, &procmask, 0); |
| 1869 | #endif | ||
| 1895 | 1870 | ||
| 1896 | if (pty_flag) | 1871 | if (pty_flag) |
| 1897 | child_setup_tty (xforkout); | 1872 | child_setup_tty (xforkout); |
| @@ -1970,19 +1945,10 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1970 | #endif | 1945 | #endif |
| 1971 | } | 1946 | } |
| 1972 | 1947 | ||
| 1973 | /* Restore the signal state whether vfork succeeded or not. | 1948 | #ifdef SIGCHLD |
| 1974 | (We will signal an error, below, if it failed.) */ | ||
| 1975 | #ifdef HAVE_WORKING_VFORK | ||
| 1976 | /* Restore the parent's signal handlers. */ | ||
| 1977 | sigaction (SIGINT, &sigint_action, 0); | ||
| 1978 | sigaction (SIGQUIT, &sigquit_action, 0); | ||
| 1979 | sigaction (SIGPIPE, &sigpipe_action, 0); | ||
| 1980 | #ifdef AIX | ||
| 1981 | sigaction (SIGHUP, &sighup_action, 0); | ||
| 1982 | #endif | ||
| 1983 | #endif /* HAVE_WORKING_VFORK */ | ||
| 1984 | /* Stop blocking signals in the parent. */ | 1949 | /* Stop blocking signals in the parent. */ |
| 1985 | pthread_sigmask (SIG_SETMASK, &procmask, 0); | 1950 | pthread_sigmask (SIG_SETMASK, &procmask, 0); |
| 1951 | #endif | ||
| 1986 | 1952 | ||
| 1987 | /* Now generate the error if vfork failed. */ | 1953 | /* Now generate the error if vfork failed. */ |
| 1988 | if (pid < 0) | 1954 | if (pid < 0) |
| @@ -2560,7 +2526,7 @@ static Lisp_Object | |||
| 2560 | make_serial_process_unwind (Lisp_Object proc) | 2526 | make_serial_process_unwind (Lisp_Object proc) |
| 2561 | { | 2527 | { |
| 2562 | if (!PROCESSP (proc)) | 2528 | if (!PROCESSP (proc)) |
| 2563 | abort (); | 2529 | emacs_abort (); |
| 2564 | remove_process (proc); | 2530 | remove_process (proc); |
| 2565 | return Qnil; | 2531 | return Qnil; |
| 2566 | } | 2532 | } |
| @@ -3397,7 +3363,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3397 | if (socktype == SOCK_DGRAM) | 3363 | if (socktype == SOCK_DGRAM) |
| 3398 | { | 3364 | { |
| 3399 | if (datagram_address[s].sa) | 3365 | if (datagram_address[s].sa) |
| 3400 | abort (); | 3366 | emacs_abort (); |
| 3401 | datagram_address[s].sa = xmalloc (lres->ai_addrlen); | 3367 | datagram_address[s].sa = xmalloc (lres->ai_addrlen); |
| 3402 | datagram_address[s].len = lres->ai_addrlen; | 3368 | datagram_address[s].len = lres->ai_addrlen; |
| 3403 | if (is_server) | 3369 | if (is_server) |
| @@ -3983,7 +3949,7 @@ deactivate_process (Lisp_Object proc) | |||
| 3983 | FD_CLR (inchannel, &connect_wait_mask); | 3949 | FD_CLR (inchannel, &connect_wait_mask); |
| 3984 | FD_CLR (inchannel, &write_mask); | 3950 | FD_CLR (inchannel, &write_mask); |
| 3985 | if (--num_pending_connects < 0) | 3951 | if (--num_pending_connects < 0) |
| 3986 | abort (); | 3952 | emacs_abort (); |
| 3987 | } | 3953 | } |
| 3988 | #endif | 3954 | #endif |
| 3989 | if (inchannel == max_process_desc) | 3955 | if (inchannel == max_process_desc) |
| @@ -4406,10 +4372,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4406 | Otherwise, do pending quit if requested. */ | 4372 | Otherwise, do pending quit if requested. */ |
| 4407 | if (read_kbd >= 0) | 4373 | if (read_kbd >= 0) |
| 4408 | QUIT; | 4374 | QUIT; |
| 4409 | #ifdef SYNC_INPUT | ||
| 4410 | else | 4375 | else |
| 4411 | process_pending_signals (); | 4376 | process_pending_signals (); |
| 4412 | #endif | ||
| 4413 | 4377 | ||
| 4414 | /* Exit now if the cell we're waiting for became non-nil. */ | 4378 | /* Exit now if the cell we're waiting for became non-nil. */ |
| 4415 | if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) | 4379 | if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) |
| @@ -4763,7 +4727,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4763 | Cleanup occurs c/o status_notify after SIGCLD. */ | 4727 | Cleanup occurs c/o status_notify after SIGCLD. */ |
| 4764 | no_avail = 1; /* Cannot depend on values returned */ | 4728 | no_avail = 1; /* Cannot depend on values returned */ |
| 4765 | #else | 4729 | #else |
| 4766 | abort (); | 4730 | emacs_abort (); |
| 4767 | #endif | 4731 | #endif |
| 4768 | } | 4732 | } |
| 4769 | else | 4733 | else |
| @@ -4846,7 +4810,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4846 | if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) | 4810 | if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) |
| 4847 | break; | 4811 | break; |
| 4848 | 4812 | ||
| 4849 | #ifdef SIGIO | 4813 | #ifdef USABLE_SIGIO |
| 4850 | /* If we think we have keyboard input waiting, but didn't get SIGIO, | 4814 | /* If we think we have keyboard input waiting, but didn't get SIGIO, |
| 4851 | go read it. This can happen with X on BSD after logging out. | 4815 | go read it. This can happen with X on BSD after logging out. |
| 4852 | In that case, there really is no input and no SIGIO, | 4816 | In that case, there really is no input and no SIGIO, |
| @@ -4967,8 +4931,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4967 | 4931 | ||
| 4968 | if (p->pid == -2) | 4932 | if (p->pid == -2) |
| 4969 | { | 4933 | { |
| 4970 | /* If the EIO occurs on a pty, sigchld_handler's | 4934 | /* If the EIO occurs on a pty, the SIGCHLD handler's |
| 4971 | waitpid() will not find the process object to | 4935 | waitpid call will not find the process object to |
| 4972 | delete. Do it here. */ | 4936 | delete. Do it here. */ |
| 4973 | p->tick = ++process_tick; | 4937 | p->tick = ++process_tick; |
| 4974 | pset_status (p, Qfailed); | 4938 | pset_status (p, Qfailed); |
| @@ -5004,7 +4968,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5004 | FD_CLR (channel, &connect_wait_mask); | 4968 | FD_CLR (channel, &connect_wait_mask); |
| 5005 | FD_CLR (channel, &write_mask); | 4969 | FD_CLR (channel, &write_mask); |
| 5006 | if (--num_pending_connects < 0) | 4970 | if (--num_pending_connects < 0) |
| 5007 | abort (); | 4971 | emacs_abort (); |
| 5008 | 4972 | ||
| 5009 | proc = chan_process[channel]; | 4973 | proc = chan_process[channel]; |
| 5010 | if (NILP (proc)) | 4974 | if (NILP (proc)) |
| @@ -5205,7 +5169,7 @@ read_process_output (Lisp_Object proc, register int channel) | |||
| 5205 | if (!NILP (outstream)) | 5169 | if (!NILP (outstream)) |
| 5206 | { | 5170 | { |
| 5207 | Lisp_Object text; | 5171 | Lisp_Object text; |
| 5208 | int outer_running_asynch_code = running_asynch_code; | 5172 | bool outer_running_asynch_code = running_asynch_code; |
| 5209 | int waiting = waiting_for_user_input_p; | 5173 | int waiting = waiting_for_user_input_p; |
| 5210 | 5174 | ||
| 5211 | /* No need to gcpro these, because all we do with them later | 5175 | /* No need to gcpro these, because all we do with them later |
| @@ -5308,7 +5272,7 @@ read_process_output (Lisp_Object proc, register int channel) | |||
| 5308 | } | 5272 | } |
| 5309 | 5273 | ||
| 5310 | /* If no filter, write into buffer if it isn't dead. */ | 5274 | /* If no filter, write into buffer if it isn't dead. */ |
| 5311 | else if (!NILP (p->buffer) && !NILP (BVAR (XBUFFER (p->buffer), name))) | 5275 | else if (!NILP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) |
| 5312 | { | 5276 | { |
| 5313 | Lisp_Object old_read_only; | 5277 | Lisp_Object old_read_only; |
| 5314 | ptrdiff_t old_begv, old_zv; | 5278 | ptrdiff_t old_begv, old_zv; |
| @@ -5430,19 +5394,23 @@ read_process_output (Lisp_Object proc, register int channel) | |||
| 5430 | 5394 | ||
| 5431 | /* Sending data to subprocess */ | 5395 | /* Sending data to subprocess */ |
| 5432 | 5396 | ||
| 5433 | static jmp_buf send_process_frame; | 5397 | static sys_jmp_buf send_process_frame; |
| 5434 | static Lisp_Object process_sent_to; | 5398 | static Lisp_Object process_sent_to; |
| 5435 | 5399 | ||
| 5436 | #ifndef FORWARD_SIGNAL_TO_MAIN_THREAD | 5400 | static _Noreturn void |
| 5437 | static _Noreturn void send_process_trap (int); | 5401 | handle_pipe_signal (int sig) |
| 5438 | #endif | 5402 | { |
| 5403 | sigset_t unblocked; | ||
| 5404 | sigemptyset (&unblocked); | ||
| 5405 | sigaddset (&unblocked, SIGPIPE); | ||
| 5406 | pthread_sigmask (SIG_UNBLOCK, &unblocked, 0); | ||
| 5407 | sys_longjmp (send_process_frame, 1); | ||
| 5408 | } | ||
| 5439 | 5409 | ||
| 5440 | static void | 5410 | static void |
| 5441 | send_process_trap (int ignore) | 5411 | deliver_pipe_signal (int sig) |
| 5442 | { | 5412 | { |
| 5443 | SIGNAL_THREAD_CHECK (SIGPIPE); | 5413 | handle_on_main_thread (sig, handle_pipe_signal); |
| 5444 | sigunblock (sigmask (SIGPIPE)); | ||
| 5445 | longjmp (send_process_frame, 1); | ||
| 5446 | } | 5414 | } |
| 5447 | 5415 | ||
| 5448 | /* In send_process, when a write fails temporarily, | 5416 | /* In send_process, when a write fails temporarily, |
| @@ -5535,7 +5503,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5535 | struct Lisp_Process *p = XPROCESS (proc); | 5503 | struct Lisp_Process *p = XPROCESS (proc); |
| 5536 | ssize_t rv; | 5504 | ssize_t rv; |
| 5537 | struct coding_system *coding; | 5505 | struct coding_system *coding; |
| 5538 | void (*volatile old_sigpipe) (int); | 5506 | struct sigaction old_sigpipe_action; |
| 5539 | 5507 | ||
| 5540 | if (p->raw_status_new) | 5508 | if (p->raw_status_new) |
| 5541 | update_status (p); | 5509 | update_status (p); |
| @@ -5645,7 +5613,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5645 | /* 2000-09-21: Emacs 20.7, sparc-sun-solaris-2.6, GCC 2.95.2, | 5613 | /* 2000-09-21: Emacs 20.7, sparc-sun-solaris-2.6, GCC 2.95.2, |
| 5646 | CFLAGS="-g -O": The value of the parameter `proc' is clobbered | 5614 | CFLAGS="-g -O": The value of the parameter `proc' is clobbered |
| 5647 | when returning with longjmp despite being declared volatile. */ | 5615 | when returning with longjmp despite being declared volatile. */ |
| 5648 | if (!setjmp (send_process_frame)) | 5616 | if (!sys_setjmp (send_process_frame)) |
| 5649 | { | 5617 | { |
| 5650 | p = XPROCESS (proc); /* Repair any setjmp clobbering. */ | 5618 | p = XPROCESS (proc); /* Repair any setjmp clobbering. */ |
| 5651 | process_sent_to = proc; | 5619 | process_sent_to = proc; |
| @@ -5674,7 +5642,9 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5674 | /* Send this batch, using one or more write calls. */ | 5642 | /* Send this batch, using one or more write calls. */ |
| 5675 | ptrdiff_t written = 0; | 5643 | ptrdiff_t written = 0; |
| 5676 | int outfd = p->outfd; | 5644 | int outfd = p->outfd; |
| 5677 | old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap); | 5645 | struct sigaction action; |
| 5646 | emacs_sigaction_init (&action, deliver_pipe_signal); | ||
| 5647 | sigaction (SIGPIPE, &action, &old_sigpipe_action); | ||
| 5678 | #ifdef DATAGRAM_SOCKETS | 5648 | #ifdef DATAGRAM_SOCKETS |
| 5679 | if (DATAGRAM_CHAN_P (outfd)) | 5649 | if (DATAGRAM_CHAN_P (outfd)) |
| 5680 | { | 5650 | { |
| @@ -5685,7 +5655,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5685 | written = rv; | 5655 | written = rv; |
| 5686 | else if (errno == EMSGSIZE) | 5656 | else if (errno == EMSGSIZE) |
| 5687 | { | 5657 | { |
| 5688 | signal (SIGPIPE, old_sigpipe); | 5658 | sigaction (SIGPIPE, &old_sigpipe_action, 0); |
| 5689 | report_file_error ("sending datagram", | 5659 | report_file_error ("sending datagram", |
| 5690 | Fcons (proc, Qnil)); | 5660 | Fcons (proc, Qnil)); |
| 5691 | } | 5661 | } |
| @@ -5710,7 +5680,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5710 | } | 5680 | } |
| 5711 | #endif | 5681 | #endif |
| 5712 | } | 5682 | } |
| 5713 | signal (SIGPIPE, old_sigpipe); | 5683 | sigaction (SIGPIPE, &old_sigpipe_action, 0); |
| 5714 | 5684 | ||
| 5715 | if (rv < 0) | 5685 | if (rv < 0) |
| 5716 | { | 5686 | { |
| @@ -5770,7 +5740,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5770 | } | 5740 | } |
| 5771 | else | 5741 | else |
| 5772 | { | 5742 | { |
| 5773 | signal (SIGPIPE, old_sigpipe); | 5743 | sigaction (SIGPIPE, &old_sigpipe_action, 0); |
| 5774 | proc = process_sent_to; | 5744 | proc = process_sent_to; |
| 5775 | p = XPROCESS (proc); | 5745 | p = XPROCESS (proc); |
| 5776 | p->raw_status_new = 0; | 5746 | p->raw_status_new = 0; |
| @@ -6365,15 +6335,14 @@ process has been transmitted to the serial port. */) | |||
| 6365 | #endif /* not HAVE_SHUTDOWN */ | 6335 | #endif /* not HAVE_SHUTDOWN */ |
| 6366 | new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); | 6336 | new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); |
| 6367 | if (new_outfd < 0) | 6337 | if (new_outfd < 0) |
| 6368 | abort (); | 6338 | emacs_abort (); |
| 6369 | old_outfd = XPROCESS (proc)->outfd; | 6339 | old_outfd = XPROCESS (proc)->outfd; |
| 6370 | 6340 | ||
| 6371 | if (!proc_encode_coding_system[new_outfd]) | 6341 | if (!proc_encode_coding_system[new_outfd]) |
| 6372 | proc_encode_coding_system[new_outfd] | 6342 | proc_encode_coding_system[new_outfd] |
| 6373 | = xmalloc (sizeof (struct coding_system)); | 6343 | = xmalloc (sizeof (struct coding_system)); |
| 6374 | memcpy (proc_encode_coding_system[new_outfd], | 6344 | *proc_encode_coding_system[new_outfd] |
| 6375 | proc_encode_coding_system[old_outfd], | 6345 | = *proc_encode_coding_system[old_outfd]; |
| 6376 | sizeof (struct coding_system)); | ||
| 6377 | memset (proc_encode_coding_system[old_outfd], 0, | 6346 | memset (proc_encode_coding_system[old_outfd], 0, |
| 6378 | sizeof (struct coding_system)); | 6347 | sizeof (struct coding_system)); |
| 6379 | 6348 | ||
| @@ -6408,143 +6377,135 @@ process has been transmitted to the serial port. */) | |||
| 6408 | indirectly; if it does, that is a bug */ | 6377 | indirectly; if it does, that is a bug */ |
| 6409 | 6378 | ||
| 6410 | #ifdef SIGCHLD | 6379 | #ifdef SIGCHLD |
| 6411 | static void | 6380 | |
| 6412 | sigchld_handler (int signo) | 6381 | /* Record one child's changed status. Return true if a child was found. */ |
| 6382 | static bool | ||
| 6383 | record_child_status_change (void) | ||
| 6413 | { | 6384 | { |
| 6414 | int old_errno = errno; | ||
| 6415 | Lisp_Object proc; | 6385 | Lisp_Object proc; |
| 6416 | struct Lisp_Process *p; | 6386 | struct Lisp_Process *p; |
| 6387 | pid_t pid; | ||
| 6388 | int w; | ||
| 6389 | Lisp_Object tail; | ||
| 6417 | 6390 | ||
| 6418 | SIGNAL_THREAD_CHECK (signo); | 6391 | do |
| 6419 | 6392 | pid = waitpid (-1, &w, WNOHANG | WUNTRACED); | |
| 6420 | while (1) | 6393 | while (pid < 0 && errno == EINTR); |
| 6421 | { | ||
| 6422 | pid_t pid; | ||
| 6423 | int w; | ||
| 6424 | Lisp_Object tail; | ||
| 6425 | |||
| 6426 | #ifdef WNOHANG | ||
| 6427 | #ifndef WUNTRACED | ||
| 6428 | #define WUNTRACED 0 | ||
| 6429 | #endif /* no WUNTRACED */ | ||
| 6430 | /* Keep trying to get a status until we get a definitive result. */ | ||
| 6431 | do | ||
| 6432 | { | ||
| 6433 | errno = 0; | ||
| 6434 | pid = waitpid (-1, &w, WNOHANG | WUNTRACED); | ||
| 6435 | } | ||
| 6436 | while (pid < 0 && errno == EINTR); | ||
| 6437 | |||
| 6438 | if (pid <= 0) | ||
| 6439 | { | ||
| 6440 | /* PID == 0 means no processes found, PID == -1 means a real | ||
| 6441 | failure. We have done all our job, so return. */ | ||
| 6442 | 6394 | ||
| 6443 | errno = old_errno; | 6395 | /* PID == 0 means no processes found, PID == -1 means a real failure. |
| 6444 | return; | 6396 | Either way, we have done all our job. */ |
| 6445 | } | 6397 | if (pid <= 0) |
| 6446 | #else | 6398 | return false; |
| 6447 | pid = wait (&w); | ||
| 6448 | #endif /* no WNOHANG */ | ||
| 6449 | 6399 | ||
| 6450 | /* Find the process that signaled us, and record its status. */ | 6400 | /* Find the process that signaled us, and record its status. */ |
| 6451 | 6401 | ||
| 6452 | /* The process can have been deleted by Fdelete_process. */ | 6402 | /* The process can have been deleted by Fdelete_process. */ |
| 6453 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) | 6403 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) |
| 6404 | { | ||
| 6405 | Lisp_Object xpid = XCAR (tail); | ||
| 6406 | if ((INTEGERP (xpid) && pid == XINT (xpid)) | ||
| 6407 | || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid))) | ||
| 6454 | { | 6408 | { |
| 6455 | Lisp_Object xpid = XCAR (tail); | 6409 | XSETCAR (tail, Qnil); |
| 6456 | if ((INTEGERP (xpid) && pid == XINT (xpid)) | 6410 | return true; |
| 6457 | || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid))) | ||
| 6458 | { | ||
| 6459 | XSETCAR (tail, Qnil); | ||
| 6460 | goto sigchld_end_of_loop; | ||
| 6461 | } | ||
| 6462 | } | 6411 | } |
| 6412 | } | ||
| 6463 | 6413 | ||
| 6464 | /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ | 6414 | /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ |
| 6415 | p = 0; | ||
| 6416 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6417 | { | ||
| 6418 | proc = XCDR (XCAR (tail)); | ||
| 6419 | p = XPROCESS (proc); | ||
| 6420 | if (EQ (p->type, Qreal) && p->pid == pid) | ||
| 6421 | break; | ||
| 6465 | p = 0; | 6422 | p = 0; |
| 6466 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | 6423 | } |
| 6467 | { | ||
| 6468 | proc = XCDR (XCAR (tail)); | ||
| 6469 | p = XPROCESS (proc); | ||
| 6470 | if (EQ (p->type, Qreal) && p->pid == pid) | ||
| 6471 | break; | ||
| 6472 | p = 0; | ||
| 6473 | } | ||
| 6474 | |||
| 6475 | /* Look for an asynchronous process whose pid hasn't been filled | ||
| 6476 | in yet. */ | ||
| 6477 | if (p == 0) | ||
| 6478 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6479 | { | ||
| 6480 | proc = XCDR (XCAR (tail)); | ||
| 6481 | p = XPROCESS (proc); | ||
| 6482 | if (p->pid == -1) | ||
| 6483 | break; | ||
| 6484 | p = 0; | ||
| 6485 | } | ||
| 6486 | |||
| 6487 | /* Change the status of the process that was found. */ | ||
| 6488 | if (p != 0) | ||
| 6489 | { | ||
| 6490 | int clear_desc_flag = 0; | ||
| 6491 | 6424 | ||
| 6492 | p->tick = ++process_tick; | 6425 | /* Look for an asynchronous process whose pid hasn't been filled |
| 6493 | p->raw_status = w; | 6426 | in yet. */ |
| 6494 | p->raw_status_new = 1; | 6427 | if (! p) |
| 6428 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6429 | { | ||
| 6430 | proc = XCDR (XCAR (tail)); | ||
| 6431 | p = XPROCESS (proc); | ||
| 6432 | if (p->pid == -1) | ||
| 6433 | break; | ||
| 6434 | p = 0; | ||
| 6435 | } | ||
| 6495 | 6436 | ||
| 6496 | /* If process has terminated, stop waiting for its output. */ | 6437 | /* Change the status of the process that was found. */ |
| 6497 | if ((WIFSIGNALED (w) || WIFEXITED (w)) | 6438 | if (p) |
| 6498 | && p->infd >= 0) | 6439 | { |
| 6499 | clear_desc_flag = 1; | 6440 | int clear_desc_flag = 0; |
| 6500 | 6441 | ||
| 6501 | /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */ | 6442 | p->tick = ++process_tick; |
| 6502 | if (clear_desc_flag) | 6443 | p->raw_status = w; |
| 6503 | { | 6444 | p->raw_status_new = 1; |
| 6504 | FD_CLR (p->infd, &input_wait_mask); | ||
| 6505 | FD_CLR (p->infd, &non_keyboard_wait_mask); | ||
| 6506 | } | ||
| 6507 | 6445 | ||
| 6508 | /* Tell wait_reading_process_output that it needs to wake up and | 6446 | /* If process has terminated, stop waiting for its output. */ |
| 6509 | look around. */ | 6447 | if ((WIFSIGNALED (w) || WIFEXITED (w)) |
| 6510 | if (input_available_clear_time) | 6448 | && p->infd >= 0) |
| 6511 | *input_available_clear_time = make_emacs_time (0, 0); | 6449 | clear_desc_flag = 1; |
| 6512 | } | ||
| 6513 | 6450 | ||
| 6514 | /* There was no asynchronous process found for that pid: we have | 6451 | /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */ |
| 6515 | a synchronous process. */ | 6452 | if (clear_desc_flag) |
| 6516 | else | ||
| 6517 | { | 6453 | { |
| 6518 | synch_process_alive = 0; | 6454 | FD_CLR (p->infd, &input_wait_mask); |
| 6519 | 6455 | FD_CLR (p->infd, &non_keyboard_wait_mask); | |
| 6520 | /* Report the status of the synchronous process. */ | ||
| 6521 | if (WIFEXITED (w)) | ||
| 6522 | synch_process_retcode = WEXITSTATUS (w); | ||
| 6523 | else if (WIFSIGNALED (w)) | ||
| 6524 | synch_process_termsig = WTERMSIG (w); | ||
| 6525 | |||
| 6526 | /* Tell wait_reading_process_output that it needs to wake up and | ||
| 6527 | look around. */ | ||
| 6528 | if (input_available_clear_time) | ||
| 6529 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6530 | } | 6456 | } |
| 6531 | 6457 | ||
| 6532 | sigchld_end_of_loop: | 6458 | /* Tell wait_reading_process_output that it needs to wake up and |
| 6533 | ; | 6459 | look around. */ |
| 6460 | if (input_available_clear_time) | ||
| 6461 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6462 | } | ||
| 6463 | /* There was no asynchronous process found for that pid: we have | ||
| 6464 | a synchronous process. */ | ||
| 6465 | else | ||
| 6466 | { | ||
| 6467 | synch_process_alive = 0; | ||
| 6468 | |||
| 6469 | /* Report the status of the synchronous process. */ | ||
| 6470 | if (WIFEXITED (w)) | ||
| 6471 | synch_process_retcode = WEXITSTATUS (w); | ||
| 6472 | else if (WIFSIGNALED (w)) | ||
| 6473 | synch_process_termsig = WTERMSIG (w); | ||
| 6474 | |||
| 6475 | /* Tell wait_reading_process_output that it needs to wake up and | ||
| 6476 | look around. */ | ||
| 6477 | if (input_available_clear_time) | ||
| 6478 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6479 | } | ||
| 6480 | |||
| 6481 | return true; | ||
| 6482 | } | ||
| 6534 | 6483 | ||
| 6535 | /* On some systems, we must return right away. | 6484 | /* On some systems, the SIGCHLD handler must return right away. If |
| 6536 | If any more processes want to signal us, we will | 6485 | any more processes want to signal us, we will get another signal. |
| 6537 | get another signal. | 6486 | Otherwise, loop around to use up all the processes that have |
| 6538 | Otherwise (on systems that have WNOHANG), loop around | 6487 | something to tell us. */ |
| 6539 | to use up all the processes that have something to tell us. */ | ||
| 6540 | #if (defined WINDOWSNT \ | 6488 | #if (defined WINDOWSNT \ |
| 6541 | || (defined USG && !defined GNU_LINUX \ | 6489 | || (defined USG && !defined GNU_LINUX \ |
| 6542 | && !(defined HPUX && defined WNOHANG))) | 6490 | && !(defined HPUX && defined WNOHANG))) |
| 6543 | errno = old_errno; | 6491 | enum { CAN_HANDLE_MULTIPLE_CHILDREN = 0 }; |
| 6544 | return; | 6492 | #else |
| 6545 | #endif /* USG, but not HPUX with WNOHANG */ | 6493 | enum { CAN_HANDLE_MULTIPLE_CHILDREN = 1 }; |
| 6546 | } | 6494 | #endif |
| 6495 | |||
| 6496 | static void | ||
| 6497 | handle_child_signal (int sig) | ||
| 6498 | { | ||
| 6499 | while (record_child_status_change () && CAN_HANDLE_MULTIPLE_CHILDREN) | ||
| 6500 | continue; | ||
| 6547 | } | 6501 | } |
| 6502 | |||
| 6503 | static void | ||
| 6504 | deliver_child_signal (int sig) | ||
| 6505 | { | ||
| 6506 | handle_on_main_thread (sig, handle_child_signal); | ||
| 6507 | } | ||
| 6508 | |||
| 6548 | #endif /* SIGCHLD */ | 6509 | #endif /* SIGCHLD */ |
| 6549 | 6510 | ||
| 6550 | 6511 | ||
| @@ -6569,9 +6530,9 @@ static void | |||
| 6569 | exec_sentinel (Lisp_Object proc, Lisp_Object reason) | 6530 | exec_sentinel (Lisp_Object proc, Lisp_Object reason) |
| 6570 | { | 6531 | { |
| 6571 | Lisp_Object sentinel, odeactivate; | 6532 | Lisp_Object sentinel, odeactivate; |
| 6572 | register struct Lisp_Process *p = XPROCESS (proc); | 6533 | struct Lisp_Process *p = XPROCESS (proc); |
| 6573 | ptrdiff_t count = SPECPDL_INDEX (); | 6534 | ptrdiff_t count = SPECPDL_INDEX (); |
| 6574 | int outer_running_asynch_code = running_asynch_code; | 6535 | bool outer_running_asynch_code = running_asynch_code; |
| 6575 | int waiting = waiting_for_user_input_p; | 6536 | int waiting = waiting_for_user_input_p; |
| 6576 | 6537 | ||
| 6577 | if (inhibit_sentinels) | 6538 | if (inhibit_sentinels) |
| @@ -6734,7 +6695,7 @@ status_notify (struct Lisp_Process *deleting_process) | |||
| 6734 | 6695 | ||
| 6735 | /* Avoid error if buffer is deleted | 6696 | /* Avoid error if buffer is deleted |
| 6736 | (probably that's why the process is dead, too) */ | 6697 | (probably that's why the process is dead, too) */ |
| 6737 | if (NILP (BVAR (XBUFFER (buffer), name))) | 6698 | if (!BUFFER_LIVE_P (XBUFFER (buffer))) |
| 6738 | continue; | 6699 | continue; |
| 6739 | Fset_buffer (buffer); | 6700 | Fset_buffer (buffer); |
| 6740 | 6701 | ||
| @@ -6866,7 +6827,7 @@ delete_gpm_wait_descriptor (int desc) | |||
| 6866 | 6827 | ||
| 6867 | # endif | 6828 | # endif |
| 6868 | 6829 | ||
| 6869 | # ifdef SIGIO | 6830 | # ifdef USABLE_SIGIO |
| 6870 | 6831 | ||
| 6871 | /* Return nonzero if *MASK has a bit set | 6832 | /* Return nonzero if *MASK has a bit set |
| 6872 | that corresponds to one of the keyboard input descriptors. */ | 6833 | that corresponds to one of the keyboard input descriptors. */ |
| @@ -7398,7 +7359,11 @@ init_process_emacs (void) | |||
| 7398 | #ifndef CANNOT_DUMP | 7359 | #ifndef CANNOT_DUMP |
| 7399 | if (! noninteractive || initialized) | 7360 | if (! noninteractive || initialized) |
| 7400 | #endif | 7361 | #endif |
| 7401 | signal (SIGCHLD, sigchld_handler); | 7362 | { |
| 7363 | struct sigaction action; | ||
| 7364 | emacs_sigaction_init (&action, deliver_child_signal); | ||
| 7365 | sigaction (SIGCHLD, &action, 0); | ||
| 7366 | } | ||
| 7402 | #endif | 7367 | #endif |
| 7403 | 7368 | ||
| 7404 | FD_ZERO (&input_wait_mask); | 7369 | FD_ZERO (&input_wait_mask); |