diff options
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 299 |
1 files changed, 151 insertions, 148 deletions
diff --git a/src/process.c b/src/process.c index 04b6abe50a7..0cc9bc353a1 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -23,7 +23,6 @@ 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> | 28 | #include <setjmp.h> |
| @@ -124,6 +123,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 124 | #include "xgselect.h" | 123 | #include "xgselect.h" |
| 125 | #endif | 124 | #endif |
| 126 | 125 | ||
| 126 | #ifndef WNOHANG | ||
| 127 | # undef waitpid | ||
| 128 | # define waitpid(pid, status, options) wait (status) | ||
| 129 | #endif | ||
| 130 | #ifndef WUNTRACED | ||
| 131 | # define WUNTRACED 0 | ||
| 132 | #endif | ||
| 133 | |||
| 127 | /* Work around GCC 4.7.0 bug with strict overflow checking; see | 134 | /* Work around GCC 4.7.0 bug with strict overflow checking; see |
| 128 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. | 135 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. |
| 129 | These lines can be removed once the GCC bug is fixed. */ | 136 | These lines can be removed once the GCC bug is fixed. */ |
| @@ -801,7 +808,7 @@ get_process (register Lisp_Object name) | |||
| 801 | #ifdef SIGCHLD | 808 | #ifdef SIGCHLD |
| 802 | /* Fdelete_process promises to immediately forget about the process, but in | 809 | /* Fdelete_process promises to immediately forget about the process, but in |
| 803 | reality, Emacs needs to remember those processes until they have been | 810 | reality, Emacs needs to remember those processes until they have been |
| 804 | treated by sigchld_handler; otherwise this handler would consider the | 811 | treated by the SIGCHLD handler; otherwise this handler would consider the |
| 805 | process as being synchronous and say that the synchronous process is | 812 | process as being synchronous and say that the synchronous process is |
| 806 | dead. */ | 813 | dead. */ |
| 807 | static Lisp_Object deleted_pid_list; | 814 | static Lisp_Object deleted_pid_list; |
| @@ -849,7 +856,8 @@ nil, indicating the current buffer's process. */) | |||
| 849 | #endif | 856 | #endif |
| 850 | { | 857 | { |
| 851 | Fkill_process (process, Qnil); | 858 | Fkill_process (process, Qnil); |
| 852 | /* Do this now, since remove_process will make sigchld_handler do nothing. */ | 859 | /* Do this now, since remove_process will make the |
| 860 | SIGCHLD handler do nothing. */ | ||
| 853 | pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil))); | 861 | pset_status (p, Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil))); |
| 854 | p->tick = ++process_tick; | 862 | p->tick = ++process_tick; |
| 855 | status_notify (p); | 863 | status_notify (p); |
| @@ -1577,7 +1585,7 @@ static Lisp_Object | |||
| 1577 | start_process_unwind (Lisp_Object proc) | 1585 | start_process_unwind (Lisp_Object proc) |
| 1578 | { | 1586 | { |
| 1579 | if (!PROCESSP (proc)) | 1587 | if (!PROCESSP (proc)) |
| 1580 | abort (); | 1588 | emacs_abort (); |
| 1581 | 1589 | ||
| 1582 | /* Was PROC started successfully? | 1590 | /* Was PROC started successfully? |
| 1583 | -2 is used for a pty with no process, eg for gdb. */ | 1591 | -2 is used for a pty with no process, eg for gdb. */ |
| @@ -1603,8 +1611,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1603 | #if !defined (WINDOWSNT) && defined (FD_CLOEXEC) | 1611 | #if !defined (WINDOWSNT) && defined (FD_CLOEXEC) |
| 1604 | int wait_child_setup[2]; | 1612 | int wait_child_setup[2]; |
| 1605 | #endif | 1613 | #endif |
| 1606 | sigset_t procmask; | 1614 | sigset_t blocked, procmask; |
| 1607 | sigset_t blocked; | ||
| 1608 | struct sigaction sigint_action; | 1615 | struct sigaction sigint_action; |
| 1609 | struct sigaction sigquit_action; | 1616 | struct sigaction sigquit_action; |
| 1610 | struct sigaction sigpipe_action; | 1617 | struct sigaction sigpipe_action; |
| @@ -1728,7 +1735,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1728 | if (inchannel > max_process_desc) | 1735 | if (inchannel > max_process_desc) |
| 1729 | max_process_desc = inchannel; | 1736 | max_process_desc = inchannel; |
| 1730 | 1737 | ||
| 1731 | /* Until we store the proper pid, enable sigchld_handler | 1738 | /* Until we store the proper pid, enable the SIGCHLD handler |
| 1732 | to recognize an unknown pid as standing for this process. | 1739 | to recognize an unknown pid as standing for this process. |
| 1733 | It is very important not to let this `marker' value stay | 1740 | It is very important not to let this `marker' value stay |
| 1734 | in the table after this function has returned; if it does | 1741 | in the table after this function has returned; if it does |
| @@ -1756,12 +1763,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1756 | int xforkin = forkin; | 1763 | int xforkin = forkin; |
| 1757 | int xforkout = forkout; | 1764 | int xforkout = forkout; |
| 1758 | 1765 | ||
| 1759 | #if 0 /* This was probably a mistake--it duplicates code later on, | ||
| 1760 | but fails to handle all the cases. */ | ||
| 1761 | /* Make sure SIGCHLD is not blocked in the child. */ | ||
| 1762 | sigsetmask (SIGEMPTYMASK); | ||
| 1763 | #endif | ||
| 1764 | |||
| 1765 | /* Make the pty be the controlling terminal of the process. */ | 1766 | /* Make the pty be the controlling terminal of the process. */ |
| 1766 | #ifdef HAVE_PTYS | 1767 | #ifdef HAVE_PTYS |
| 1767 | /* First, disconnect its current controlling terminal. */ | 1768 | /* First, disconnect its current controlling terminal. */ |
| @@ -2550,7 +2551,7 @@ static Lisp_Object | |||
| 2550 | make_serial_process_unwind (Lisp_Object proc) | 2551 | make_serial_process_unwind (Lisp_Object proc) |
| 2551 | { | 2552 | { |
| 2552 | if (!PROCESSP (proc)) | 2553 | if (!PROCESSP (proc)) |
| 2553 | abort (); | 2554 | emacs_abort (); |
| 2554 | remove_process (proc); | 2555 | remove_process (proc); |
| 2555 | return Qnil; | 2556 | return Qnil; |
| 2556 | } | 2557 | } |
| @@ -3387,7 +3388,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3387 | if (socktype == SOCK_DGRAM) | 3388 | if (socktype == SOCK_DGRAM) |
| 3388 | { | 3389 | { |
| 3389 | if (datagram_address[s].sa) | 3390 | if (datagram_address[s].sa) |
| 3390 | abort (); | 3391 | emacs_abort (); |
| 3391 | datagram_address[s].sa = xmalloc (lres->ai_addrlen); | 3392 | datagram_address[s].sa = xmalloc (lres->ai_addrlen); |
| 3392 | datagram_address[s].len = lres->ai_addrlen; | 3393 | datagram_address[s].len = lres->ai_addrlen; |
| 3393 | if (is_server) | 3394 | if (is_server) |
| @@ -3973,7 +3974,7 @@ deactivate_process (Lisp_Object proc) | |||
| 3973 | FD_CLR (inchannel, &connect_wait_mask); | 3974 | FD_CLR (inchannel, &connect_wait_mask); |
| 3974 | FD_CLR (inchannel, &write_mask); | 3975 | FD_CLR (inchannel, &write_mask); |
| 3975 | if (--num_pending_connects < 0) | 3976 | if (--num_pending_connects < 0) |
| 3976 | abort (); | 3977 | emacs_abort (); |
| 3977 | } | 3978 | } |
| 3978 | #endif | 3979 | #endif |
| 3979 | if (inchannel == max_process_desc) | 3980 | if (inchannel == max_process_desc) |
| @@ -4752,7 +4753,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4752 | Cleanup occurs c/o status_notify after SIGCLD. */ | 4753 | Cleanup occurs c/o status_notify after SIGCLD. */ |
| 4753 | no_avail = 1; /* Cannot depend on values returned */ | 4754 | no_avail = 1; /* Cannot depend on values returned */ |
| 4754 | #else | 4755 | #else |
| 4755 | abort (); | 4756 | emacs_abort (); |
| 4756 | #endif | 4757 | #endif |
| 4757 | } | 4758 | } |
| 4758 | else | 4759 | else |
| @@ -4956,8 +4957,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4956 | 4957 | ||
| 4957 | if (p->pid == -2) | 4958 | if (p->pid == -2) |
| 4958 | { | 4959 | { |
| 4959 | /* If the EIO occurs on a pty, sigchld_handler's | 4960 | /* If the EIO occurs on a pty, the SIGCHLD handler's |
| 4960 | waitpid() will not find the process object to | 4961 | waitpid call will not find the process object to |
| 4961 | delete. Do it here. */ | 4962 | delete. Do it here. */ |
| 4962 | p->tick = ++process_tick; | 4963 | p->tick = ++process_tick; |
| 4963 | pset_status (p, Qfailed); | 4964 | pset_status (p, Qfailed); |
| @@ -4993,7 +4994,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4993 | FD_CLR (channel, &connect_wait_mask); | 4994 | FD_CLR (channel, &connect_wait_mask); |
| 4994 | FD_CLR (channel, &write_mask); | 4995 | FD_CLR (channel, &write_mask); |
| 4995 | if (--num_pending_connects < 0) | 4996 | if (--num_pending_connects < 0) |
| 4996 | abort (); | 4997 | emacs_abort (); |
| 4997 | 4998 | ||
| 4998 | proc = chan_process[channel]; | 4999 | proc = chan_process[channel]; |
| 4999 | if (NILP (proc)) | 5000 | if (NILP (proc)) |
| @@ -5422,16 +5423,20 @@ read_process_output (Lisp_Object proc, register int channel) | |||
| 5422 | static jmp_buf send_process_frame; | 5423 | static jmp_buf send_process_frame; |
| 5423 | static Lisp_Object process_sent_to; | 5424 | static Lisp_Object process_sent_to; |
| 5424 | 5425 | ||
| 5425 | #ifndef FORWARD_SIGNAL_TO_MAIN_THREAD | 5426 | static _Noreturn void |
| 5426 | static _Noreturn void send_process_trap (int); | 5427 | handle_pipe_signal (int sig) |
| 5427 | #endif | 5428 | { |
| 5429 | sigset_t unblocked; | ||
| 5430 | sigemptyset (&unblocked); | ||
| 5431 | sigaddset (&unblocked, SIGPIPE); | ||
| 5432 | pthread_sigmask (SIG_UNBLOCK, &unblocked, 0); | ||
| 5433 | _longjmp (send_process_frame, 1); | ||
| 5434 | } | ||
| 5428 | 5435 | ||
| 5429 | static void | 5436 | static void |
| 5430 | send_process_trap (int ignore) | 5437 | deliver_pipe_signal (int sig) |
| 5431 | { | 5438 | { |
| 5432 | SIGNAL_THREAD_CHECK (SIGPIPE); | 5439 | handle_on_main_thread (sig, handle_pipe_signal); |
| 5433 | sigunblock (sigmask (SIGPIPE)); | ||
| 5434 | longjmp (send_process_frame, 1); | ||
| 5435 | } | 5440 | } |
| 5436 | 5441 | ||
| 5437 | /* In send_process, when a write fails temporarily, | 5442 | /* In send_process, when a write fails temporarily, |
| @@ -5524,7 +5529,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5524 | struct Lisp_Process *p = XPROCESS (proc); | 5529 | struct Lisp_Process *p = XPROCESS (proc); |
| 5525 | ssize_t rv; | 5530 | ssize_t rv; |
| 5526 | struct coding_system *coding; | 5531 | struct coding_system *coding; |
| 5527 | void (*volatile old_sigpipe) (int); | 5532 | struct sigaction old_sigpipe_action; |
| 5528 | 5533 | ||
| 5529 | if (p->raw_status_new) | 5534 | if (p->raw_status_new) |
| 5530 | update_status (p); | 5535 | update_status (p); |
| @@ -5634,7 +5639,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5634 | /* 2000-09-21: Emacs 20.7, sparc-sun-solaris-2.6, GCC 2.95.2, | 5639 | /* 2000-09-21: Emacs 20.7, sparc-sun-solaris-2.6, GCC 2.95.2, |
| 5635 | CFLAGS="-g -O": The value of the parameter `proc' is clobbered | 5640 | CFLAGS="-g -O": The value of the parameter `proc' is clobbered |
| 5636 | when returning with longjmp despite being declared volatile. */ | 5641 | when returning with longjmp despite being declared volatile. */ |
| 5637 | if (!setjmp (send_process_frame)) | 5642 | if (!_setjmp (send_process_frame)) |
| 5638 | { | 5643 | { |
| 5639 | p = XPROCESS (proc); /* Repair any setjmp clobbering. */ | 5644 | p = XPROCESS (proc); /* Repair any setjmp clobbering. */ |
| 5640 | process_sent_to = proc; | 5645 | process_sent_to = proc; |
| @@ -5663,7 +5668,9 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5663 | /* Send this batch, using one or more write calls. */ | 5668 | /* Send this batch, using one or more write calls. */ |
| 5664 | ptrdiff_t written = 0; | 5669 | ptrdiff_t written = 0; |
| 5665 | int outfd = p->outfd; | 5670 | int outfd = p->outfd; |
| 5666 | old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap); | 5671 | struct sigaction action; |
| 5672 | emacs_sigaction_init (&action, deliver_pipe_signal); | ||
| 5673 | sigaction (SIGPIPE, &action, &old_sigpipe_action); | ||
| 5667 | #ifdef DATAGRAM_SOCKETS | 5674 | #ifdef DATAGRAM_SOCKETS |
| 5668 | if (DATAGRAM_CHAN_P (outfd)) | 5675 | if (DATAGRAM_CHAN_P (outfd)) |
| 5669 | { | 5676 | { |
| @@ -5674,7 +5681,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5674 | written = rv; | 5681 | written = rv; |
| 5675 | else if (errno == EMSGSIZE) | 5682 | else if (errno == EMSGSIZE) |
| 5676 | { | 5683 | { |
| 5677 | signal (SIGPIPE, old_sigpipe); | 5684 | sigaction (SIGPIPE, &old_sigpipe_action, 0); |
| 5678 | report_file_error ("sending datagram", | 5685 | report_file_error ("sending datagram", |
| 5679 | Fcons (proc, Qnil)); | 5686 | Fcons (proc, Qnil)); |
| 5680 | } | 5687 | } |
| @@ -5699,7 +5706,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5699 | } | 5706 | } |
| 5700 | #endif | 5707 | #endif |
| 5701 | } | 5708 | } |
| 5702 | signal (SIGPIPE, old_sigpipe); | 5709 | sigaction (SIGPIPE, &old_sigpipe_action, 0); |
| 5703 | 5710 | ||
| 5704 | if (rv < 0) | 5711 | if (rv < 0) |
| 5705 | { | 5712 | { |
| @@ -5759,7 +5766,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, | |||
| 5759 | } | 5766 | } |
| 5760 | else | 5767 | else |
| 5761 | { | 5768 | { |
| 5762 | signal (SIGPIPE, old_sigpipe); | 5769 | sigaction (SIGPIPE, &old_sigpipe_action, 0); |
| 5763 | proc = process_sent_to; | 5770 | proc = process_sent_to; |
| 5764 | p = XPROCESS (proc); | 5771 | p = XPROCESS (proc); |
| 5765 | p->raw_status_new = 0; | 5772 | p->raw_status_new = 0; |
| @@ -6354,7 +6361,7 @@ process has been transmitted to the serial port. */) | |||
| 6354 | #endif /* not HAVE_SHUTDOWN */ | 6361 | #endif /* not HAVE_SHUTDOWN */ |
| 6355 | new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); | 6362 | new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); |
| 6356 | if (new_outfd < 0) | 6363 | if (new_outfd < 0) |
| 6357 | abort (); | 6364 | emacs_abort (); |
| 6358 | old_outfd = XPROCESS (proc)->outfd; | 6365 | old_outfd = XPROCESS (proc)->outfd; |
| 6359 | 6366 | ||
| 6360 | if (!proc_encode_coding_system[new_outfd]) | 6367 | if (!proc_encode_coding_system[new_outfd]) |
| @@ -6397,143 +6404,135 @@ process has been transmitted to the serial port. */) | |||
| 6397 | indirectly; if it does, that is a bug */ | 6404 | indirectly; if it does, that is a bug */ |
| 6398 | 6405 | ||
| 6399 | #ifdef SIGCHLD | 6406 | #ifdef SIGCHLD |
| 6400 | static void | 6407 | |
| 6401 | sigchld_handler (int signo) | 6408 | /* Record one child's changed status. Return true if a child was found. */ |
| 6409 | static bool | ||
| 6410 | record_child_status_change (void) | ||
| 6402 | { | 6411 | { |
| 6403 | int old_errno = errno; | ||
| 6404 | Lisp_Object proc; | 6412 | Lisp_Object proc; |
| 6405 | struct Lisp_Process *p; | 6413 | struct Lisp_Process *p; |
| 6414 | pid_t pid; | ||
| 6415 | int w; | ||
| 6416 | Lisp_Object tail; | ||
| 6406 | 6417 | ||
| 6407 | SIGNAL_THREAD_CHECK (signo); | 6418 | do |
| 6408 | 6419 | pid = waitpid (-1, &w, WNOHANG | WUNTRACED); | |
| 6409 | while (1) | 6420 | while (pid < 0 && errno == EINTR); |
| 6410 | { | ||
| 6411 | pid_t pid; | ||
| 6412 | int w; | ||
| 6413 | Lisp_Object tail; | ||
| 6414 | |||
| 6415 | #ifdef WNOHANG | ||
| 6416 | #ifndef WUNTRACED | ||
| 6417 | #define WUNTRACED 0 | ||
| 6418 | #endif /* no WUNTRACED */ | ||
| 6419 | /* Keep trying to get a status until we get a definitive result. */ | ||
| 6420 | do | ||
| 6421 | { | ||
| 6422 | errno = 0; | ||
| 6423 | pid = waitpid (-1, &w, WNOHANG | WUNTRACED); | ||
| 6424 | } | ||
| 6425 | while (pid < 0 && errno == EINTR); | ||
| 6426 | |||
| 6427 | if (pid <= 0) | ||
| 6428 | { | ||
| 6429 | /* PID == 0 means no processes found, PID == -1 means a real | ||
| 6430 | failure. We have done all our job, so return. */ | ||
| 6431 | 6421 | ||
| 6432 | errno = old_errno; | 6422 | /* PID == 0 means no processes found, PID == -1 means a real failure. |
| 6433 | return; | 6423 | Either way, we have done all our job. */ |
| 6434 | } | 6424 | if (pid <= 0) |
| 6435 | #else | 6425 | return false; |
| 6436 | pid = wait (&w); | ||
| 6437 | #endif /* no WNOHANG */ | ||
| 6438 | 6426 | ||
| 6439 | /* Find the process that signaled us, and record its status. */ | 6427 | /* Find the process that signaled us, and record its status. */ |
| 6440 | 6428 | ||
| 6441 | /* The process can have been deleted by Fdelete_process. */ | 6429 | /* The process can have been deleted by Fdelete_process. */ |
| 6442 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) | 6430 | for (tail = deleted_pid_list; CONSP (tail); tail = XCDR (tail)) |
| 6431 | { | ||
| 6432 | Lisp_Object xpid = XCAR (tail); | ||
| 6433 | if ((INTEGERP (xpid) && pid == XINT (xpid)) | ||
| 6434 | || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid))) | ||
| 6443 | { | 6435 | { |
| 6444 | Lisp_Object xpid = XCAR (tail); | 6436 | XSETCAR (tail, Qnil); |
| 6445 | if ((INTEGERP (xpid) && pid == XINT (xpid)) | 6437 | return true; |
| 6446 | || (FLOATP (xpid) && pid == XFLOAT_DATA (xpid))) | ||
| 6447 | { | ||
| 6448 | XSETCAR (tail, Qnil); | ||
| 6449 | goto sigchld_end_of_loop; | ||
| 6450 | } | ||
| 6451 | } | 6438 | } |
| 6439 | } | ||
| 6452 | 6440 | ||
| 6453 | /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ | 6441 | /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ |
| 6442 | p = 0; | ||
| 6443 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6444 | { | ||
| 6445 | proc = XCDR (XCAR (tail)); | ||
| 6446 | p = XPROCESS (proc); | ||
| 6447 | if (EQ (p->type, Qreal) && p->pid == pid) | ||
| 6448 | break; | ||
| 6454 | p = 0; | 6449 | p = 0; |
| 6455 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | 6450 | } |
| 6456 | { | ||
| 6457 | proc = XCDR (XCAR (tail)); | ||
| 6458 | p = XPROCESS (proc); | ||
| 6459 | if (EQ (p->type, Qreal) && p->pid == pid) | ||
| 6460 | break; | ||
| 6461 | p = 0; | ||
| 6462 | } | ||
| 6463 | |||
| 6464 | /* Look for an asynchronous process whose pid hasn't been filled | ||
| 6465 | in yet. */ | ||
| 6466 | if (p == 0) | ||
| 6467 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6468 | { | ||
| 6469 | proc = XCDR (XCAR (tail)); | ||
| 6470 | p = XPROCESS (proc); | ||
| 6471 | if (p->pid == -1) | ||
| 6472 | break; | ||
| 6473 | p = 0; | ||
| 6474 | } | ||
| 6475 | |||
| 6476 | /* Change the status of the process that was found. */ | ||
| 6477 | if (p != 0) | ||
| 6478 | { | ||
| 6479 | int clear_desc_flag = 0; | ||
| 6480 | 6451 | ||
| 6481 | p->tick = ++process_tick; | 6452 | /* Look for an asynchronous process whose pid hasn't been filled |
| 6482 | p->raw_status = w; | 6453 | in yet. */ |
| 6483 | p->raw_status_new = 1; | 6454 | if (! p) |
| 6455 | for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) | ||
| 6456 | { | ||
| 6457 | proc = XCDR (XCAR (tail)); | ||
| 6458 | p = XPROCESS (proc); | ||
| 6459 | if (p->pid == -1) | ||
| 6460 | break; | ||
| 6461 | p = 0; | ||
| 6462 | } | ||
| 6484 | 6463 | ||
| 6485 | /* If process has terminated, stop waiting for its output. */ | 6464 | /* Change the status of the process that was found. */ |
| 6486 | if ((WIFSIGNALED (w) || WIFEXITED (w)) | 6465 | if (p) |
| 6487 | && p->infd >= 0) | 6466 | { |
| 6488 | clear_desc_flag = 1; | 6467 | int clear_desc_flag = 0; |
| 6489 | 6468 | ||
| 6490 | /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */ | 6469 | p->tick = ++process_tick; |
| 6491 | if (clear_desc_flag) | 6470 | p->raw_status = w; |
| 6492 | { | 6471 | p->raw_status_new = 1; |
| 6493 | FD_CLR (p->infd, &input_wait_mask); | ||
| 6494 | FD_CLR (p->infd, &non_keyboard_wait_mask); | ||
| 6495 | } | ||
| 6496 | 6472 | ||
| 6497 | /* Tell wait_reading_process_output that it needs to wake up and | 6473 | /* If process has terminated, stop waiting for its output. */ |
| 6498 | look around. */ | 6474 | if ((WIFSIGNALED (w) || WIFEXITED (w)) |
| 6499 | if (input_available_clear_time) | 6475 | && p->infd >= 0) |
| 6500 | *input_available_clear_time = make_emacs_time (0, 0); | 6476 | clear_desc_flag = 1; |
| 6501 | } | ||
| 6502 | 6477 | ||
| 6503 | /* There was no asynchronous process found for that pid: we have | 6478 | /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */ |
| 6504 | a synchronous process. */ | 6479 | if (clear_desc_flag) |
| 6505 | else | ||
| 6506 | { | 6480 | { |
| 6507 | synch_process_alive = 0; | 6481 | FD_CLR (p->infd, &input_wait_mask); |
| 6508 | 6482 | FD_CLR (p->infd, &non_keyboard_wait_mask); | |
| 6509 | /* Report the status of the synchronous process. */ | ||
| 6510 | if (WIFEXITED (w)) | ||
| 6511 | synch_process_retcode = WEXITSTATUS (w); | ||
| 6512 | else if (WIFSIGNALED (w)) | ||
| 6513 | synch_process_termsig = WTERMSIG (w); | ||
| 6514 | |||
| 6515 | /* Tell wait_reading_process_output that it needs to wake up and | ||
| 6516 | look around. */ | ||
| 6517 | if (input_available_clear_time) | ||
| 6518 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6519 | } | 6483 | } |
| 6520 | 6484 | ||
| 6521 | sigchld_end_of_loop: | 6485 | /* Tell wait_reading_process_output that it needs to wake up and |
| 6522 | ; | 6486 | look around. */ |
| 6487 | if (input_available_clear_time) | ||
| 6488 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6489 | } | ||
| 6490 | /* There was no asynchronous process found for that pid: we have | ||
| 6491 | a synchronous process. */ | ||
| 6492 | else | ||
| 6493 | { | ||
| 6494 | synch_process_alive = 0; | ||
| 6495 | |||
| 6496 | /* Report the status of the synchronous process. */ | ||
| 6497 | if (WIFEXITED (w)) | ||
| 6498 | synch_process_retcode = WEXITSTATUS (w); | ||
| 6499 | else if (WIFSIGNALED (w)) | ||
| 6500 | synch_process_termsig = WTERMSIG (w); | ||
| 6501 | |||
| 6502 | /* Tell wait_reading_process_output that it needs to wake up and | ||
| 6503 | look around. */ | ||
| 6504 | if (input_available_clear_time) | ||
| 6505 | *input_available_clear_time = make_emacs_time (0, 0); | ||
| 6506 | } | ||
| 6507 | |||
| 6508 | return true; | ||
| 6509 | } | ||
| 6523 | 6510 | ||
| 6524 | /* On some systems, we must return right away. | 6511 | /* On some systems, the SIGCHLD handler must return right away. If |
| 6525 | If any more processes want to signal us, we will | 6512 | any more processes want to signal us, we will get another signal. |
| 6526 | get another signal. | 6513 | Otherwise, loop around to use up all the processes that have |
| 6527 | Otherwise (on systems that have WNOHANG), loop around | 6514 | something to tell us. */ |
| 6528 | to use up all the processes that have something to tell us. */ | ||
| 6529 | #if (defined WINDOWSNT \ | 6515 | #if (defined WINDOWSNT \ |
| 6530 | || (defined USG && !defined GNU_LINUX \ | 6516 | || (defined USG && !defined GNU_LINUX \ |
| 6531 | && !(defined HPUX && defined WNOHANG))) | 6517 | && !(defined HPUX && defined WNOHANG))) |
| 6532 | errno = old_errno; | 6518 | enum { CAN_HANDLE_MULTIPLE_CHILDREN = 0 }; |
| 6533 | return; | 6519 | #else |
| 6534 | #endif /* USG, but not HPUX with WNOHANG */ | 6520 | enum { CAN_HANDLE_MULTIPLE_CHILDREN = 1 }; |
| 6535 | } | 6521 | #endif |
| 6522 | |||
| 6523 | static void | ||
| 6524 | handle_child_signal (int sig) | ||
| 6525 | { | ||
| 6526 | while (record_child_status_change () && CAN_HANDLE_MULTIPLE_CHILDREN) | ||
| 6527 | continue; | ||
| 6536 | } | 6528 | } |
| 6529 | |||
| 6530 | static void | ||
| 6531 | deliver_child_signal (int sig) | ||
| 6532 | { | ||
| 6533 | handle_on_main_thread (sig, handle_child_signal); | ||
| 6534 | } | ||
| 6535 | |||
| 6537 | #endif /* SIGCHLD */ | 6536 | #endif /* SIGCHLD */ |
| 6538 | 6537 | ||
| 6539 | 6538 | ||
| @@ -7387,7 +7386,11 @@ init_process_emacs (void) | |||
| 7387 | #ifndef CANNOT_DUMP | 7386 | #ifndef CANNOT_DUMP |
| 7388 | if (! noninteractive || initialized) | 7387 | if (! noninteractive || initialized) |
| 7389 | #endif | 7388 | #endif |
| 7390 | signal (SIGCHLD, sigchld_handler); | 7389 | { |
| 7390 | struct sigaction action; | ||
| 7391 | emacs_sigaction_init (&action, deliver_child_signal); | ||
| 7392 | sigaction (SIGCHLD, &action, 0); | ||
| 7393 | } | ||
| 7391 | #endif | 7394 | #endif |
| 7392 | 7395 | ||
| 7393 | FD_ZERO (&input_wait_mask); | 7396 | FD_ZERO (&input_wait_mask); |