diff options
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 354 |
1 files changed, 105 insertions, 249 deletions
diff --git a/src/process.c b/src/process.c index 0036ce595f5..7b21d060cf8 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -91,6 +91,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 91 | #include <pty.h> | 91 | #include <pty.h> |
| 92 | #endif | 92 | #endif |
| 93 | 93 | ||
| 94 | #include <c-ctype.h> | ||
| 95 | #include <sig2str.h> | ||
| 96 | |||
| 94 | #endif /* subprocesses */ | 97 | #endif /* subprocesses */ |
| 95 | 98 | ||
| 96 | #include "systime.h" | 99 | #include "systime.h" |
| @@ -773,13 +776,22 @@ get_process (register Lisp_Object name) | |||
| 773 | } | 776 | } |
| 774 | 777 | ||
| 775 | 778 | ||
| 776 | #ifdef SIGCHLD | ||
| 777 | /* Fdelete_process promises to immediately forget about the process, but in | 779 | /* Fdelete_process promises to immediately forget about the process, but in |
| 778 | reality, Emacs needs to remember those processes until they have been | 780 | reality, Emacs needs to remember those processes until they have been |
| 779 | treated by the SIGCHLD handler and waitpid has been invoked on them; | 781 | treated by the SIGCHLD handler and waitpid has been invoked on them; |
| 780 | otherwise they might fill up the kernel's process table. */ | 782 | otherwise they might fill up the kernel's process table. |
| 783 | |||
| 784 | Some processes created by call-process are also put onto this list. */ | ||
| 781 | static Lisp_Object deleted_pid_list; | 785 | static Lisp_Object deleted_pid_list; |
| 782 | #endif | 786 | |
| 787 | void | ||
| 788 | record_deleted_pid (pid_t pid) | ||
| 789 | { | ||
| 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 | } | ||
| 783 | 795 | ||
| 784 | DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0, | 796 | DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0, |
| 785 | doc: /* Delete PROCESS: kill it and forget about it immediately. | 797 | doc: /* Delete PROCESS: kill it and forget about it immediately. |
| @@ -800,32 +812,22 @@ nil, indicating the current buffer's process. */) | |||
| 800 | status_notify (p); | 812 | status_notify (p); |
| 801 | redisplay_preserve_echo_area (13); | 813 | redisplay_preserve_echo_area (13); |
| 802 | } | 814 | } |
| 803 | else if (p->infd >= 0) | 815 | else |
| 804 | { | 816 | { |
| 805 | #ifdef SIGCHLD | 817 | if (p->alive) |
| 806 | Lisp_Object symbol; | 818 | record_kill_process (p); |
| 807 | pid_t pid = p->pid; | 819 | |
| 808 | 820 | if (p->infd >= 0) | |
| 809 | /* No problem storing the pid here, as it is still in Vprocess_alist. */ | ||
| 810 | deleted_pid_list = Fcons (make_fixnum_or_float (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. */ | ||
| 814 | if (p->raw_status_new) | ||
| 815 | update_status (p); | ||
| 816 | symbol = p->status; | ||
| 817 | if (CONSP (p->status)) | ||
| 818 | symbol = XCAR (p->status); | ||
| 819 | if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)) | ||
| 820 | deleted_pid_list | ||
| 821 | = Fdelete (make_fixnum_or_float (pid), deleted_pid_list); | ||
| 822 | else | ||
| 823 | #endif | ||
| 824 | { | 821 | { |
| 825 | Fkill_process (process, Qnil); | 822 | /* Update P's status, since record_kill_process will make the |
| 826 | /* Do this now, since remove_process will make the | 823 | SIGCHLD handler update deleted_pid_list, not *P. */ |
| 827 | SIGCHLD handler do nothing. */ | 824 | Lisp_Object symbol; |
| 828 | pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil))); | 825 | if (p->raw_status_new) |
| 826 | update_status (p); | ||
| 827 | symbol = CONSP (p->status) ? XCAR (p->status) : p->status; | ||
| 828 | if (! (EQ (symbol, Qsignal) || EQ (symbol, Qexit))) | ||
| 829 | pset_status (p, list2 (Qsignal, make_number (SIGKILL))); | ||
| 830 | |||
| 829 | p->tick = ++process_tick; | 831 | p->tick = ++process_tick; |
| 830 | status_notify (p); | 832 | status_notify (p); |
| 831 | redisplay_preserve_echo_area (13); | 833 | redisplay_preserve_echo_area (13); |
| @@ -1578,17 +1580,12 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1578 | #ifndef WINDOWSNT | 1580 | #ifndef WINDOWSNT |
| 1579 | int wait_child_setup[2]; | 1581 | int wait_child_setup[2]; |
| 1580 | #endif | 1582 | #endif |
| 1581 | #ifdef SIGCHLD | ||
| 1582 | sigset_t blocked; | 1583 | sigset_t blocked; |
| 1583 | #endif | ||
| 1584 | /* Use volatile to protect variables from being clobbered by vfork. */ | 1584 | /* Use volatile to protect variables from being clobbered by vfork. */ |
| 1585 | volatile int forkin, forkout; | 1585 | volatile int forkin, forkout; |
| 1586 | volatile int pty_flag = 0; | 1586 | volatile int pty_flag = 0; |
| 1587 | volatile Lisp_Object lisp_pty_name = Qnil; | 1587 | volatile Lisp_Object lisp_pty_name = Qnil; |
| 1588 | volatile Lisp_Object encoded_current_dir; | 1588 | volatile Lisp_Object encoded_current_dir; |
| 1589 | #if HAVE_WORKING_VFORK | ||
| 1590 | char **volatile save_environ; | ||
| 1591 | #endif | ||
| 1592 | 1589 | ||
| 1593 | inchannel = outchannel = -1; | 1590 | inchannel = outchannel = -1; |
| 1594 | 1591 | ||
| @@ -1680,19 +1677,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1680 | 1677 | ||
| 1681 | block_input (); | 1678 | block_input (); |
| 1682 | 1679 | ||
| 1683 | #ifdef SIGCHLD | ||
| 1684 | /* Block SIGCHLD until we have a chance to store the new fork's | 1680 | /* Block SIGCHLD until we have a chance to store the new fork's |
| 1685 | pid in its process structure. */ | 1681 | pid in its process structure. */ |
| 1686 | sigemptyset (&blocked); | 1682 | sigemptyset (&blocked); |
| 1687 | sigaddset (&blocked, SIGCHLD); | 1683 | sigaddset (&blocked, SIGCHLD); |
| 1688 | pthread_sigmask (SIG_BLOCK, &blocked, 0); | 1684 | pthread_sigmask (SIG_BLOCK, &blocked, 0); |
| 1689 | #endif | ||
| 1690 | |||
| 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 | 1685 | ||
| 1697 | #ifndef WINDOWSNT | 1686 | #ifndef WINDOWSNT |
| 1698 | pid = vfork (); | 1687 | pid = vfork (); |
| @@ -1800,10 +1789,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1800 | /* Emacs ignores SIGPIPE, but the child should not. */ | 1789 | /* Emacs ignores SIGPIPE, but the child should not. */ |
| 1801 | signal (SIGPIPE, SIG_DFL); | 1790 | signal (SIGPIPE, SIG_DFL); |
| 1802 | 1791 | ||
| 1803 | #ifdef SIGCHLD | ||
| 1804 | /* Stop blocking signals in the child. */ | 1792 | /* Stop blocking signals in the child. */ |
| 1805 | pthread_sigmask (SIG_SETMASK, &empty_mask, 0); | 1793 | pthread_sigmask (SIG_SETMASK, &empty_mask, 0); |
| 1806 | #endif | ||
| 1807 | 1794 | ||
| 1808 | if (pty_flag) | 1795 | if (pty_flag) |
| 1809 | child_setup_tty (xforkout); | 1796 | child_setup_tty (xforkout); |
| @@ -1819,18 +1806,12 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1819 | 1806 | ||
| 1820 | /* Back in the parent process. */ | 1807 | /* Back in the parent process. */ |
| 1821 | 1808 | ||
| 1822 | #if HAVE_WORKING_VFORK | ||
| 1823 | environ = save_environ; | ||
| 1824 | #endif | ||
| 1825 | |||
| 1826 | XPROCESS (process)->pid = pid; | 1809 | XPROCESS (process)->pid = pid; |
| 1827 | if (0 <= pid) | 1810 | if (0 <= pid) |
| 1828 | XPROCESS (process)->alive = 1; | 1811 | XPROCESS (process)->alive = 1; |
| 1829 | 1812 | ||
| 1830 | /* Stop blocking signals in the parent. */ | 1813 | /* Stop blocking signals in the parent. */ |
| 1831 | #ifdef SIGCHLD | ||
| 1832 | pthread_sigmask (SIG_SETMASK, &empty_mask, 0); | 1814 | pthread_sigmask (SIG_SETMASK, &empty_mask, 0); |
| 1833 | #endif | ||
| 1834 | unblock_input (); | 1815 | unblock_input (); |
| 1835 | 1816 | ||
| 1836 | if (pid < 0) | 1817 | if (pid < 0) |
| @@ -1874,7 +1855,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 | 1855 | /* Wait for child_setup to complete in case that vfork is |
| 1875 | actually defined as fork. The descriptor wait_child_setup[1] | 1856 | 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 | 1857 | 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. */ | 1858 | on successful execve or the _exit call in child_setup. */ |
| 1878 | { | 1859 | { |
| 1879 | char dummy; | 1860 | char dummy; |
| 1880 | 1861 | ||
| @@ -4432,14 +4413,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4432 | total_nread += nread; | 4413 | total_nread += nread; |
| 4433 | got_some_input = 1; | 4414 | got_some_input = 1; |
| 4434 | } | 4415 | } |
| 4435 | #ifdef EIO | 4416 | else if (nread == -1 && (errno == EIO || errno == EAGAIN)) |
| 4436 | else if (nread == -1 && EIO == errno) | ||
| 4437 | break; | ||
| 4438 | #endif | ||
| 4439 | #ifdef EAGAIN | ||
| 4440 | else if (nread == -1 && EAGAIN == errno) | ||
| 4441 | break; | 4417 | break; |
| 4442 | #endif | ||
| 4443 | #ifdef EWOULDBLOCK | 4418 | #ifdef EWOULDBLOCK |
| 4444 | else if (nread == -1 && EWOULDBLOCK == errno) | 4419 | else if (nread == -1 && EWOULDBLOCK == errno) |
| 4445 | break; | 4420 | break; |
| @@ -4628,7 +4603,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4628 | yielding EBADF here or at select() call above. | 4603 | yielding EBADF here or at select() call above. |
| 4629 | So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF | 4604 | So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF |
| 4630 | in m/ibmrt-aix.h), and here we just ignore the select error. | 4605 | in m/ibmrt-aix.h), and here we just ignore the select error. |
| 4631 | Cleanup occurs c/o status_notify after SIGCLD. */ | 4606 | Cleanup occurs c/o status_notify after SIGCHLD. */ |
| 4632 | no_avail = 1; /* Cannot depend on values returned */ | 4607 | no_avail = 1; /* Cannot depend on values returned */ |
| 4633 | #else | 4608 | #else |
| 4634 | emacs_abort (); | 4609 | emacs_abort (); |
| @@ -4826,10 +4801,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4826 | #endif /* HAVE_PTYS */ | 4801 | #endif /* HAVE_PTYS */ |
| 4827 | /* If we can detect process termination, don't consider the | 4802 | /* If we can detect process termination, don't consider the |
| 4828 | process gone just because its pipe is closed. */ | 4803 | process gone just because its pipe is closed. */ |
| 4829 | #ifdef SIGCHLD | ||
| 4830 | else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc)) | 4804 | else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc)) |
| 4831 | ; | 4805 | ; |
| 4832 | #endif | ||
| 4833 | else | 4806 | else |
| 4834 | { | 4807 | { |
| 4835 | /* Preserve status of processes already terminated. */ | 4808 | /* Preserve status of processes already terminated. */ |
| @@ -5517,13 +5490,10 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len, | |||
| 5517 | 5490 | ||
| 5518 | if (rv < 0) | 5491 | if (rv < 0) |
| 5519 | { | 5492 | { |
| 5520 | if (0 | 5493 | if (errno == EAGAIN |
| 5521 | #ifdef EWOULDBLOCK | 5494 | #ifdef EWOULDBLOCK |
| 5522 | || errno == EWOULDBLOCK | 5495 | || errno == EWOULDBLOCK |
| 5523 | #endif | 5496 | #endif |
| 5524 | #ifdef EAGAIN | ||
| 5525 | || errno == EAGAIN | ||
| 5526 | #endif | ||
| 5527 | ) | 5497 | ) |
| 5528 | /* Buffer is full. Wait, accepting input; | 5498 | /* Buffer is full. Wait, accepting input; |
| 5529 | that may allow the program | 5499 | that may allow the program |
| @@ -5695,7 +5665,7 @@ return t unconditionally. */) | |||
| 5695 | 5665 | ||
| 5696 | If we can, we try to signal PROCESS by sending control characters | 5666 | If we can, we try to signal PROCESS by sending control characters |
| 5697 | down the pty. This allows us to signal inferiors who have changed | 5667 | down the pty. This allows us to signal inferiors who have changed |
| 5698 | their uid, for which killpg would return an EPERM error. */ | 5668 | their uid, for which kill would return an EPERM error. */ |
| 5699 | 5669 | ||
| 5700 | static void | 5670 | static void |
| 5701 | process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, | 5671 | process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, |
| @@ -5833,7 +5803,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, | |||
| 5833 | if (!NILP (current_group)) | 5803 | if (!NILP (current_group)) |
| 5834 | { | 5804 | { |
| 5835 | if (ioctl (p->infd, TIOCSIGSEND, signo) == -1) | 5805 | if (ioctl (p->infd, TIOCSIGSEND, signo) == -1) |
| 5836 | EMACS_KILLPG (gid, signo); | 5806 | kill (-gid, signo); |
| 5837 | } | 5807 | } |
| 5838 | else | 5808 | else |
| 5839 | { | 5809 | { |
| @@ -5841,7 +5811,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, | |||
| 5841 | kill (gid, signo); | 5811 | kill (gid, signo); |
| 5842 | } | 5812 | } |
| 5843 | #else /* ! defined (TIOCSIGSEND) */ | 5813 | #else /* ! defined (TIOCSIGSEND) */ |
| 5844 | EMACS_KILLPG (gid, signo); | 5814 | kill (-gid, signo); |
| 5845 | #endif /* ! defined (TIOCSIGSEND) */ | 5815 | #endif /* ! defined (TIOCSIGSEND) */ |
| 5846 | } | 5816 | } |
| 5847 | 5817 | ||
| @@ -5946,6 +5916,27 @@ traffic. */) | |||
| 5946 | return process; | 5916 | return process; |
| 5947 | } | 5917 | } |
| 5948 | 5918 | ||
| 5919 | /* Return the integer value of the signal whose abbreviation is ABBR, | ||
| 5920 | or a negative number if there is no such signal. */ | ||
| 5921 | static int | ||
| 5922 | abbr_to_signal (char const *name) | ||
| 5923 | { | ||
| 5924 | int i, signo; | ||
| 5925 | char sigbuf[20]; /* Large enough for all valid signal abbreviations. */ | ||
| 5926 | |||
| 5927 | if (!strncmp (name, "SIG", 3) || !strncmp (name, "sig", 3)) | ||
| 5928 | name += 3; | ||
| 5929 | |||
| 5930 | for (i = 0; i < sizeof sigbuf; i++) | ||
| 5931 | { | ||
| 5932 | sigbuf[i] = c_toupper (name[i]); | ||
| 5933 | if (! sigbuf[i]) | ||
| 5934 | return str2sig (sigbuf, &signo) == 0 ? signo : -1; | ||
| 5935 | } | ||
| 5936 | |||
| 5937 | return -1; | ||
| 5938 | } | ||
| 5939 | |||
| 5949 | DEFUN ("signal-process", Fsignal_process, Ssignal_process, | 5940 | DEFUN ("signal-process", Fsignal_process, Ssignal_process, |
| 5950 | 2, 2, "sProcess (name or number): \nnSignal code: ", | 5941 | 2, 2, "sProcess (name or number): \nnSignal code: ", |
| 5951 | doc: /* Send PROCESS the signal with code SIGCODE. | 5942 | doc: /* Send PROCESS the signal with code SIGCODE. |
| @@ -5956,6 +5947,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */) | |||
| 5956 | (Lisp_Object process, Lisp_Object sigcode) | 5947 | (Lisp_Object process, Lisp_Object sigcode) |
| 5957 | { | 5948 | { |
| 5958 | pid_t pid; | 5949 | pid_t pid; |
| 5950 | int signo; | ||
| 5959 | 5951 | ||
| 5960 | if (STRINGP (process)) | 5952 | if (STRINGP (process)) |
| 5961 | { | 5953 | { |
| @@ -5985,12 +5977,11 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */) | |||
| 5985 | error ("Cannot signal process %s", SDATA (XPROCESS (process)->name)); | 5977 | error ("Cannot signal process %s", SDATA (XPROCESS (process)->name)); |
| 5986 | } | 5978 | } |
| 5987 | 5979 | ||
| 5988 | #define parse_signal(NAME, VALUE) \ | ||
| 5989 | else if (!xstrcasecmp (name, NAME)) \ | ||
| 5990 | XSETINT (sigcode, VALUE) | ||
| 5991 | |||
| 5992 | if (INTEGERP (sigcode)) | 5980 | if (INTEGERP (sigcode)) |
| 5993 | CHECK_TYPE_RANGED_INTEGER (int, sigcode); | 5981 | { |
| 5982 | CHECK_TYPE_RANGED_INTEGER (int, sigcode); | ||
| 5983 | signo = XINT (sigcode); | ||
| 5984 | } | ||
| 5994 | else | 5985 | else |
| 5995 | { | 5986 | { |
| 5996 | char *name; | 5987 | char *name; |
| @@ -5998,96 +5989,12 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */) | |||
| 5998 | CHECK_SYMBOL (sigcode); | 5989 | CHECK_SYMBOL (sigcode); |
| 5999 | name = SSDATA (SYMBOL_NAME (sigcode)); | 5990 | name = SSDATA (SYMBOL_NAME (sigcode)); |
| 6000 | 5991 | ||
| 6001 | if (!strncmp (name, "SIG", 3) || !strncmp (name, "sig", 3)) | 5992 | signo = abbr_to_signal (name); |
| 6002 | name += 3; | 5993 | if (signo < 0) |
| 6003 | |||
| 6004 | if (0) | ||
| 6005 | ; | ||
| 6006 | #ifdef SIGUSR1 | ||
| 6007 | parse_signal ("usr1", SIGUSR1); | ||
| 6008 | #endif | ||
| 6009 | #ifdef SIGUSR2 | ||
| 6010 | parse_signal ("usr2", SIGUSR2); | ||
| 6011 | #endif | ||
| 6012 | parse_signal ("term", SIGTERM); | ||
| 6013 | #ifdef SIGHUP | ||
| 6014 | parse_signal ("hup", SIGHUP); | ||
| 6015 | #endif | ||
| 6016 | parse_signal ("int", SIGINT); | ||
| 6017 | #ifdef SIGQUIT | ||
| 6018 | parse_signal ("quit", SIGQUIT); | ||
| 6019 | #endif | ||
| 6020 | parse_signal ("ill", SIGILL); | ||
| 6021 | parse_signal ("abrt", SIGABRT); | ||
| 6022 | #ifdef SIGEMT | ||
| 6023 | parse_signal ("emt", SIGEMT); | ||
| 6024 | #endif | ||
| 6025 | #ifdef SIGKILL | ||
| 6026 | parse_signal ("kill", SIGKILL); | ||
| 6027 | #endif | ||
| 6028 | parse_signal ("fpe", SIGFPE); | ||
| 6029 | #ifdef SIGBUS | ||
| 6030 | parse_signal ("bus", SIGBUS); | ||
| 6031 | #endif | ||
| 6032 | parse_signal ("segv", SIGSEGV); | ||
| 6033 | #ifdef SIGSYS | ||
| 6034 | parse_signal ("sys", SIGSYS); | ||
| 6035 | #endif | ||
| 6036 | #ifdef SIGPIPE | ||
| 6037 | parse_signal ("pipe", SIGPIPE); | ||
| 6038 | #endif | ||
| 6039 | #ifdef SIGALRM | ||
| 6040 | parse_signal ("alrm", SIGALRM); | ||
| 6041 | #endif | ||
| 6042 | #ifdef SIGURG | ||
| 6043 | parse_signal ("urg", SIGURG); | ||
| 6044 | #endif | ||
| 6045 | #ifdef SIGSTOP | ||
| 6046 | parse_signal ("stop", SIGSTOP); | ||
| 6047 | #endif | ||
| 6048 | #ifdef SIGTSTP | ||
| 6049 | parse_signal ("tstp", SIGTSTP); | ||
| 6050 | #endif | ||
| 6051 | #ifdef SIGCONT | ||
| 6052 | parse_signal ("cont", SIGCONT); | ||
| 6053 | #endif | ||
| 6054 | #ifdef SIGCHLD | ||
| 6055 | parse_signal ("chld", SIGCHLD); | ||
| 6056 | #endif | ||
| 6057 | #ifdef SIGTTIN | ||
| 6058 | parse_signal ("ttin", SIGTTIN); | ||
| 6059 | #endif | ||
| 6060 | #ifdef SIGTTOU | ||
| 6061 | parse_signal ("ttou", SIGTTOU); | ||
| 6062 | #endif | ||
| 6063 | #ifdef SIGIO | ||
| 6064 | parse_signal ("io", SIGIO); | ||
| 6065 | #endif | ||
| 6066 | #ifdef SIGXCPU | ||
| 6067 | parse_signal ("xcpu", SIGXCPU); | ||
| 6068 | #endif | ||
| 6069 | #ifdef SIGXFSZ | ||
| 6070 | parse_signal ("xfsz", SIGXFSZ); | ||
| 6071 | #endif | ||
| 6072 | #ifdef SIGVTALRM | ||
| 6073 | parse_signal ("vtalrm", SIGVTALRM); | ||
| 6074 | #endif | ||
| 6075 | #ifdef SIGPROF | ||
| 6076 | parse_signal ("prof", SIGPROF); | ||
| 6077 | #endif | ||
| 6078 | #ifdef SIGWINCH | ||
| 6079 | parse_signal ("winch", SIGWINCH); | ||
| 6080 | #endif | ||
| 6081 | #ifdef SIGINFO | ||
| 6082 | parse_signal ("info", SIGINFO); | ||
| 6083 | #endif | ||
| 6084 | else | ||
| 6085 | error ("Undefined signal name %s", name); | 5994 | error ("Undefined signal name %s", name); |
| 6086 | } | 5995 | } |
| 6087 | 5996 | ||
| 6088 | #undef parse_signal | 5997 | return make_number (kill (pid, signo)); |
| 6089 | |||
| 6090 | return make_number (kill (pid, XINT (sigcode))); | ||
| 6091 | } | 5998 | } |
| 6092 | 5999 | ||
| 6093 | DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0, | 6000 | DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0, |
| @@ -6169,35 +6076,35 @@ process has been transmitted to the serial port. */) | |||
| 6169 | return process; | 6076 | return process; |
| 6170 | } | 6077 | } |
| 6171 | 6078 | ||
| 6172 | /* If the status of the process DESIRED has changed, return true and | 6079 | /* The main Emacs thread records child processes in three places: |
| 6173 | set *STATUS to its exit status; otherwise, return false. | 6080 | |
| 6174 | If HAVE is nonnegative, assume that HAVE = waitpid (HAVE, STATUS, ...) | 6081 | - Vprocess_alist, for asynchronous subprocesses, which are child |
| 6175 | has already been invoked, and do not invoke waitpid again. */ | 6082 | processes visible to Lisp. |
| 6176 | 6083 | ||
| 6177 | static bool | 6084 | - deleted_pid_list, for child processes invisible to Lisp, |
| 6178 | process_status_retrieved (pid_t desired, pid_t have, int *status) | 6085 | typically because of delete-process. These are recorded so that |
| 6179 | { | 6086 | the processes can be reaped when they exit, so that the operating |
| 6180 | if (have < 0) | 6087 | system's process table is not cluttered by zombies. |
| 6181 | { | 6088 | |
| 6182 | /* Invoke waitpid only with a known process ID; do not invoke | 6089 | - the local variable PID in Fcall_process, call_process_cleanup and |
| 6183 | waitpid with a nonpositive argument. Otherwise, Emacs might | 6090 | call_process_kill, for synchronous subprocesses. |
| 6184 | reap an unwanted process by mistake. For example, invoking | 6091 | record_unwind_protect is used to make sure this process is not |
| 6185 | waitpid (-1, ...) can mess up glib by reaping glib's subprocesses, | 6092 | forgotten: if the user interrupts call-process and the child |
| 6186 | so that another thread running glib won't find them. */ | 6093 | process refuses to exit immediately even with two C-g's, |
| 6187 | do | 6094 | call_process_kill adds PID's contents to deleted_pid_list before |
| 6188 | have = waitpid (desired, status, WNOHANG | WUNTRACED); | 6095 | returning. |
| 6189 | while (have < 0 && errno == EINTR); | 6096 | |
| 6190 | } | 6097 | The main Emacs thread invokes waitpid only on child processes that |
| 6191 | 6098 | it creates and that have not been reaped. This avoid races on | |
| 6192 | return have == desired; | 6099 | platforms such as GTK, where other threads create their own |
| 6193 | } | 6100 | subprocesses which the main thread should not reap. For example, |
| 6194 | 6101 | if the main thread attempted to reap an already-reaped child, it | |
| 6195 | /* If PID is nonnegative, the child process PID with wait status W has | 6102 | might inadvertently reap a GTK-created process that happened to |
| 6196 | changed its status; record this and return true. | 6103 | have the same process ID. */ |
| 6197 | 6104 | ||
| 6198 | If PID is negative, ignore W, and look for known child processes | 6105 | /* Handle a SIGCHLD signal by looking for known child processes of |
| 6199 | of Emacs whose status have changed. For each one found, record its new | 6106 | Emacs whose status have changed. For each one found, record its |
| 6200 | status. | 6107 | new status. |
| 6201 | 6108 | ||
| 6202 | All we do is change the status; we do not run sentinels or print | 6109 | All we do is change the status; we do not run sentinels or print |
| 6203 | notifications. That is saved for the next time keyboard input is | 6110 | notifications. That is saved for the next time keyboard input is |
| @@ -6220,20 +6127,15 @@ process_status_retrieved (pid_t desired, pid_t have, int *status) | |||
| 6220 | ** Malloc WARNING: This should never call malloc either directly or | 6127 | ** Malloc WARNING: This should never call malloc either directly or |
| 6221 | indirectly; if it does, that is a bug */ | 6128 | indirectly; if it does, that is a bug */ |
| 6222 | 6129 | ||
| 6223 | void | 6130 | static void |
| 6224 | record_child_status_change (pid_t pid, int w) | 6131 | handle_child_signal (int sig) |
| 6225 | { | 6132 | { |
| 6226 | #ifdef SIGCHLD | ||
| 6227 | |||
| 6228 | /* Record at most one child only if we already know one child that | ||
| 6229 | has exited. */ | ||
| 6230 | bool record_at_most_one_child = 0 <= pid; | ||
| 6231 | |||
| 6232 | Lisp_Object tail; | 6133 | Lisp_Object tail; |
| 6233 | 6134 | ||
| 6234 | /* Find the process that signaled us, and record its status. */ | 6135 | /* Find the process that signaled us, and record its status. */ |
| 6235 | 6136 | ||
| 6236 | /* The process can have been deleted by Fdelete_process. */ | 6137 | /* The process can have been deleted by Fdelete_process, or have |
| 6138 | been started asynchronously by Fcall_process. */ | ||
| 6237 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) | 6139 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) |
| 6238 | { | 6140 | { |
| 6239 | bool all_pids_are_fixnums | 6141 | bool all_pids_are_fixnums |
| @@ -6247,12 +6149,8 @@ record_child_status_change (pid_t pid, int w) | |||
| 6247 | deleted_pid = XINT (xpid); | 6149 | deleted_pid = XINT (xpid); |
| 6248 | else | 6150 | else |
| 6249 | deleted_pid = XFLOAT_DATA (xpid); | 6151 | deleted_pid = XFLOAT_DATA (xpid); |
| 6250 | if (process_status_retrieved (deleted_pid, pid, &w)) | 6152 | if (child_status_changed (deleted_pid, 0, 0)) |
| 6251 | { | 6153 | XSETCAR (tail, Qnil); |
| 6252 | XSETCAR (tail, Qnil); | ||
| 6253 | if (record_at_most_one_child) | ||
| 6254 | return; | ||
| 6255 | } | ||
| 6256 | } | 6154 | } |
| 6257 | } | 6155 | } |
| 6258 | 6156 | ||
| @@ -6261,15 +6159,17 @@ record_child_status_change (pid_t pid, int w) | |||
| 6261 | { | 6159 | { |
| 6262 | Lisp_Object proc = XCDR (XCAR (tail)); | 6160 | Lisp_Object proc = XCDR (XCAR (tail)); |
| 6263 | struct Lisp_Process *p = XPROCESS (proc); | 6161 | struct Lisp_Process *p = XPROCESS (proc); |
| 6264 | if (p->alive && process_status_retrieved (p->pid, pid, &w)) | 6162 | int status; |
| 6163 | |||
| 6164 | if (p->alive && child_status_changed (p->pid, &status, WUNTRACED)) | ||
| 6265 | { | 6165 | { |
| 6266 | /* Change the status of the process that was found. */ | 6166 | /* Change the status of the process that was found. */ |
| 6267 | p->tick = ++process_tick; | 6167 | p->tick = ++process_tick; |
| 6268 | p->raw_status = w; | 6168 | p->raw_status = status; |
| 6269 | p->raw_status_new = 1; | 6169 | p->raw_status_new = 1; |
| 6270 | 6170 | ||
| 6271 | /* If process has terminated, stop waiting for its output. */ | 6171 | /* If process has terminated, stop waiting for its output. */ |
| 6272 | if (WIFSIGNALED (w) || WIFEXITED (w)) | 6172 | if (WIFSIGNALED (status) || WIFEXITED (status)) |
| 6273 | { | 6173 | { |
| 6274 | int clear_desc_flag = 0; | 6174 | int clear_desc_flag = 0; |
| 6275 | p->alive = 0; | 6175 | p->alive = 0; |
| @@ -6283,44 +6183,8 @@ record_child_status_change (pid_t pid, int w) | |||
| 6283 | FD_CLR (p->infd, &non_keyboard_wait_mask); | 6183 | FD_CLR (p->infd, &non_keyboard_wait_mask); |
| 6284 | } | 6184 | } |
| 6285 | } | 6185 | } |
| 6286 | |||
| 6287 | /* Tell wait_reading_process_output that it needs to wake up and | ||
| 6288 | look around. */ | ||
| 6289 | if (input_available_clear_time) | ||
| 6290 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6291 | |||
| 6292 | if (record_at_most_one_child) | ||
| 6293 | return; | ||
| 6294 | } | 6186 | } |
| 6295 | } | 6187 | } |
| 6296 | |||
| 6297 | if (0 <= pid) | ||
| 6298 | { | ||
| 6299 | /* The caller successfully waited for a pid but no asynchronous | ||
| 6300 | process was found for it, so this is a synchronous process. */ | ||
| 6301 | |||
| 6302 | synch_process_alive = 0; | ||
| 6303 | |||
| 6304 | /* Report the status of the synchronous process. */ | ||
| 6305 | if (WIFEXITED (w)) | ||
| 6306 | synch_process_retcode = WEXITSTATUS (w); | ||
| 6307 | else if (WIFSIGNALED (w)) | ||
| 6308 | synch_process_termsig = WTERMSIG (w); | ||
| 6309 | |||
| 6310 | /* Tell wait_reading_process_output that it needs to wake up and | ||
| 6311 | look around. */ | ||
| 6312 | if (input_available_clear_time) | ||
| 6313 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6314 | } | ||
| 6315 | #endif | ||
| 6316 | } | ||
| 6317 | |||
| 6318 | #ifdef SIGCHLD | ||
| 6319 | |||
| 6320 | static void | ||
| 6321 | handle_child_signal (int sig) | ||
| 6322 | { | ||
| 6323 | record_child_status_change (-1, 0); | ||
| 6324 | } | 6188 | } |
| 6325 | 6189 | ||
| 6326 | static void | 6190 | static void |
| @@ -6328,8 +6192,6 @@ deliver_child_signal (int sig) | |||
| 6328 | { | 6192 | { |
| 6329 | deliver_process_signal (sig, handle_child_signal); | 6193 | deliver_process_signal (sig, handle_child_signal); |
| 6330 | } | 6194 | } |
| 6331 | |||
| 6332 | #endif /* SIGCHLD */ | ||
| 6333 | 6195 | ||
| 6334 | 6196 | ||
| 6335 | static Lisp_Object | 6197 | static Lisp_Object |
| @@ -7178,7 +7040,6 @@ init_process_emacs (void) | |||
| 7178 | 7040 | ||
| 7179 | inhibit_sentinels = 0; | 7041 | inhibit_sentinels = 0; |
| 7180 | 7042 | ||
| 7181 | #ifdef SIGCHLD | ||
| 7182 | #ifndef CANNOT_DUMP | 7043 | #ifndef CANNOT_DUMP |
| 7183 | if (! noninteractive || initialized) | 7044 | if (! noninteractive || initialized) |
| 7184 | #endif | 7045 | #endif |
| @@ -7187,7 +7048,6 @@ init_process_emacs (void) | |||
| 7187 | emacs_sigaction_init (&action, deliver_child_signal); | 7048 | emacs_sigaction_init (&action, deliver_child_signal); |
| 7188 | sigaction (SIGCHLD, &action, 0); | 7049 | sigaction (SIGCHLD, &action, 0); |
| 7189 | } | 7050 | } |
| 7190 | #endif | ||
| 7191 | 7051 | ||
| 7192 | FD_ZERO (&input_wait_mask); | 7052 | FD_ZERO (&input_wait_mask); |
| 7193 | FD_ZERO (&non_keyboard_wait_mask); | 7053 | FD_ZERO (&non_keyboard_wait_mask); |
| @@ -7214,9 +7074,7 @@ init_process_emacs (void) | |||
| 7214 | #endif | 7074 | #endif |
| 7215 | 7075 | ||
| 7216 | Vprocess_alist = Qnil; | 7076 | Vprocess_alist = Qnil; |
| 7217 | #ifdef SIGCHLD | ||
| 7218 | deleted_pid_list = Qnil; | 7077 | deleted_pid_list = Qnil; |
| 7219 | #endif | ||
| 7220 | for (i = 0; i < MAXDESC; i++) | 7078 | for (i = 0; i < MAXDESC; i++) |
| 7221 | { | 7079 | { |
| 7222 | chan_process[i] = Qnil; | 7080 | chan_process[i] = Qnil; |
| @@ -7343,9 +7201,7 @@ syms_of_process (void) | |||
| 7343 | DEFSYM (Qlast_nonmenu_event, "last-nonmenu-event"); | 7201 | DEFSYM (Qlast_nonmenu_event, "last-nonmenu-event"); |
| 7344 | 7202 | ||
| 7345 | staticpro (&Vprocess_alist); | 7203 | staticpro (&Vprocess_alist); |
| 7346 | #ifdef SIGCHLD | ||
| 7347 | staticpro (&deleted_pid_list); | 7204 | staticpro (&deleted_pid_list); |
| 7348 | #endif | ||
| 7349 | 7205 | ||
| 7350 | #endif /* subprocesses */ | 7206 | #endif /* subprocesses */ |
| 7351 | 7207 | ||