X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/1fa2385302f5b2e5bb17c8aad3cb4e320512ca46..2e5a663126a0260f5a8bb9d12b8c02c3745ea94b:/src/process.c diff --git a/src/process.c b/src/process.c index de2edad07b..de7fc14797 100644 --- a/src/process.c +++ b/src/process.c @@ -1,6 +1,6 @@ /* Asynchronous subprocess control for GNU Emacs. -Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2011 +Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -93,8 +93,8 @@ along with GNU Emacs. If not, see . */ #include "systty.h" #include "window.h" -#include "buffer.h" #include "character.h" +#include "buffer.h" #include "coding.h" #include "process.h" #include "frame.h" @@ -120,6 +120,13 @@ along with GNU Emacs. If not, see . */ #include "nsterm.h" #endif +/* Work around GCC 4.7.0 bug with strict overflow checking; see + . + These lines can be removed once the GCC bug is fixed. */ +#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wstrict-overflow" +#endif + Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid; Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime; Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs; @@ -175,9 +182,9 @@ extern int h_errno; #endif /* Number of events of change of status of a process. */ -static int process_tick; +static EMACS_INT process_tick; /* Number of events for which the user or sentinel has been notified. */ -static int update_tick; +static EMACS_INT update_tick; /* Define NON_BLOCKING_CONNECT if we can support non-blocking connects. */ @@ -221,13 +228,11 @@ static int update_tick; #endif #if !defined (ADAPTIVE_READ_BUFFERING) && !defined (NO_ADAPTIVE_READ_BUFFERING) -#ifdef EMACS_HAS_USECS #define ADAPTIVE_READ_BUFFERING #endif -#endif #ifdef ADAPTIVE_READ_BUFFERING -#define READ_OUTPUT_DELAY_INCREMENT 10000 +#define READ_OUTPUT_DELAY_INCREMENT (EMACS_TIME_RESOLUTION / 100) #define READ_OUTPUT_DELAY_MAX (READ_OUTPUT_DELAY_INCREMENT * 5) #define READ_OUTPUT_DELAY_MAX_MAX (READ_OUTPUT_DELAY_INCREMENT * 7) @@ -348,7 +353,7 @@ static struct fd_callback_data void add_read_fd (int fd, fd_callback func, void *data) { - xassert (fd < MAXDESC); + eassert (fd < MAXDESC); add_keyboard_wait_descriptor (fd); fd_callback_info[fd].func = func; @@ -361,7 +366,7 @@ add_read_fd (int fd, fd_callback func, void *data) void delete_read_fd (int fd) { - xassert (fd < MAXDESC); + eassert (fd < MAXDESC); delete_keyboard_wait_descriptor (fd); fd_callback_info[fd].condition &= ~FOR_READ; @@ -378,7 +383,7 @@ delete_read_fd (int fd) void add_write_fd (int fd, fd_callback func, void *data) { - xassert (fd < MAXDESC); + eassert (fd < MAXDESC); FD_SET (fd, &write_mask); if (fd > max_input_desc) max_input_desc = fd; @@ -395,7 +400,7 @@ delete_write_fd (int fd) { int lim = max_input_desc; - xassert (fd < MAXDESC); + eassert (fd < MAXDESC); FD_CLR (fd, &write_mask); fd_callback_info[fd].condition &= ~FOR_WRITE; if (fd_callback_info[fd].condition == 0) @@ -620,31 +625,18 @@ make_process (Lisp_Object name) printmax_t i; p = allocate_process (); - - p->infd = -1; - p->outfd = -1; - p->tick = 0; - p->update_tick = 0; - p->pid = 0; - p->pty_flag = 0; - p->raw_status_new = 0; + /* Initialize Lisp data. Note that allocate_process initializes all + Lisp data to nil, so do it only for slots which should not be nil. */ p->status = Qrun; p->mark = Fmake_marker (); - p->kill_without_query = 0; -#ifdef ADAPTIVE_READ_BUFFERING - p->adaptive_read_buffering = 0; - p->read_output_delay = 0; - p->read_output_skip = 0; -#endif + /* Initialize non-Lisp data. Note that allocate_process zeroes out all + non-Lisp data, so do it only for slots which should not be zero. */ + p->infd = -1; + p->outfd = -1; #ifdef HAVE_GNUTLS p->gnutls_initstage = GNUTLS_STAGE_EMPTY; - p->gnutls_log_level = 0; - p->gnutls_p = 0; - p->gnutls_state = NULL; - p->gnutls_x509_cred = NULL; - p->gnutls_anon_cred = NULL; #endif /* If name is already in use, modify it until it is unused. */ @@ -1063,7 +1055,9 @@ is more appropriate for saving the process buffer. Binding the variable `inherit-process-coding-system' to non-nil before starting the process is an alternative way of setting the inherit flag -for the process which will run. */) +for the process which will run. + +This function returns FLAG. */) (register Lisp_Object process, Lisp_Object flag) { CHECK_PROCESS (process); @@ -1076,7 +1070,8 @@ DEFUN ("set-process-query-on-exit-flag", 2, 2, 0, doc: /* Specify if query is needed for PROCESS when Emacs is exited. If the second argument FLAG is non-nil, Emacs will query the user before -exiting or killing a buffer if PROCESS is running. */) +exiting or killing a buffer if PROCESS is running. This function +returns FLAG. */) (register Lisp_Object process, Lisp_Object flag) { CHECK_PROCESS (process); @@ -1408,7 +1403,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) val = XCDR (Vdefault_process_coding_system); } XPROCESS (proc)->encode_coding_system = val; - /* Note: At this momemnt, the above coding system may leave + /* Note: At this moment, the above coding system may leave text-conversion or eol-conversion unspecified. They will be decided after we read output from the process and decode it by some coding system, or just before we actually send a text to @@ -1515,8 +1510,9 @@ start_process_unwind (Lisp_Object proc) if (!PROCESSP (proc)) abort (); - /* Was PROC started successfully? */ - if (XPROCESS (proc)->pid == -1) + /* Was PROC started successfully? + -2 is used for a pty with no process, eg for gdb. */ + if (XPROCESS (proc)->pid <= 0 && XPROCESS (proc)->pid != -2) remove_process (proc); return Qnil; @@ -2517,7 +2513,7 @@ could be "COM1", or "\\\\.\\COM10" for ports higher than COM9 (double the backslashes in strings). :speed SPEED -- (mandatory) is handled by `serial-process-configure', -which is called by `make-serial-process'. +which this function calls. :name NAME -- NAME is the name of the process. If NAME is not given, the value of PORT is used. @@ -2546,13 +2542,12 @@ but you can send outgoing data. The stopped state is cleared by :plist PLIST -- Install PLIST as the initial plist of the process. -:speed :bytesize :parity :stopbits :flowcontrol --- These arguments are handled by `serial-process-configure', which is -called by `make-serial-process'. +-- This function calls `serial-process-configure' to handle these +arguments. The original argument list, possibly modified by later configuration, is available via the function `process-contact'. @@ -2786,7 +2781,7 @@ The stopped state is cleared by `continue-process' and set by :filter-multibyte BOOL -- If BOOL is non-nil, strings given to the process filter are multibyte, otherwise they are unibyte. If this keyword is not specified, the strings are multibyte if -`default-enable-multibyte-characters' is non-nil. +the default value of `enable-multibyte-characters' is non-nil. :sentinel SENTINEL -- Install SENTINEL as the process sentinel. @@ -3116,7 +3111,7 @@ usage: (make-network-process &rest ARGS) */) { struct hostent *host_info_ptr; - /* gethostbyname may fail with TRY_AGAIN, but we don't honour that, + /* gethostbyname may fail with TRY_AGAIN, but we don't honor that, as it may `hang' Emacs for a very long time. */ immediate_quit = 1; QUIT; @@ -3277,7 +3272,7 @@ usage: (make-network-process &rest ARGS) */) { /* Unlike most other syscalls connect() cannot be called again. (That would return EALREADY.) The proper way to - wait for completion is select(). */ + wait for completion is pselect(). */ int sc; socklen_t len; SELECT_TYPE fdset; @@ -3285,8 +3280,7 @@ usage: (make-network-process &rest ARGS) */) FD_ZERO (&fdset); FD_SET (s, &fdset); QUIT; - sc = select (s + 1, (SELECT_TYPE *)0, &fdset, (SELECT_TYPE *)0, - (EMACS_TIME *)0); + sc = pselect (s + 1, NULL, &fdset, NULL, NULL, NULL); if (sc == -1) { if (errno == EINTR) @@ -3470,7 +3464,7 @@ usage: (make-network-process &rest ARGS) */) { /* Setup coding systems for communicating with the network stream. */ - struct gcpro inner_gcpro1; + struct gcpro gcpro1; /* Qt denotes we have not yet called Ffind_operation_coding_system. */ Lisp_Object coding_systems = Qt; Lisp_Object fargs[5], val; @@ -3487,7 +3481,7 @@ usage: (make-network-process &rest ARGS) */) || (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters)))) /* We dare not decode end-of-line format by setting VAL to Qraw_text, because the existing Emacs Lisp libraries - assume that they receive bare code including a sequene of + assume that they receive bare code including a sequence of CR LF. */ val = Qnil; else @@ -3498,9 +3492,9 @@ usage: (make-network-process &rest ARGS) */) { fargs[0] = Qopen_network_stream, fargs[1] = name, fargs[2] = buffer, fargs[3] = host, fargs[4] = service; - GCPRO1_VAR (proc, inner_gcpro); + GCPRO1 (proc); coding_systems = Ffind_operation_coding_system (5, fargs); - UNGCPRO_VAR (inner_gcpro); + UNGCPRO; } if (CONSP (coding_systems)) val = XCAR (coding_systems); @@ -3531,9 +3525,9 @@ usage: (make-network-process &rest ARGS) */) { fargs[0] = Qopen_network_stream, fargs[1] = name, fargs[2] = buffer, fargs[3] = host, fargs[4] = service; - GCPRO1_VAR (proc, inner_gcpro); + GCPRO1 (proc); coding_systems = Ffind_operation_coding_system (5, fargs); - UNGCPRO_VAR (inner_gcpro); + UNGCPRO; } } if (CONSP (coding_systems)) @@ -3713,7 +3707,7 @@ DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_inf doc: /* Return information about network interface named IFNAME. The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS), where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address, -NETMASK is the layer 3 network mask, HWADDR is the layer 2 addres, and +NETMASK is the layer 3 network mask, HWADDR is the layer 2 address, and FLAGS is the current flags of the interface. */) (Lisp_Object ifname) { @@ -3947,7 +3941,8 @@ If JUST-THIS-ONE is an integer, don't run any timers either. Return non-nil if we received any output before the timeout expired. */) (register Lisp_Object process, Lisp_Object seconds, Lisp_Object millisec, Lisp_Object just_this_one) { - int secs = -1, usecs = 0; + intmax_t secs; + int nsecs; if (! NILP (process)) CHECK_PROCESS (process); @@ -3966,17 +3961,36 @@ Return non-nil if we received any output before the timeout expired. */) } } + secs = 0; + nsecs = -1; + if (!NILP (seconds)) { - double duration = extract_float (seconds); - if (0 < duration) - duration_to_sec_usec (duration, &secs, &usecs); + if (INTEGERP (seconds)) + { + if (0 < XINT (seconds)) + { + secs = XINT (seconds); + nsecs = 0; + } + } + else if (FLOATP (seconds)) + { + if (0 < XFLOAT_DATA (seconds)) + { + EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (seconds)); + secs = min (EMACS_SECS (t), WAIT_READING_MAX); + nsecs = EMACS_NSECS (t); + } + } + else + wrong_type_argument (Qnumberp, seconds); } - else if (!NILP (process)) - secs = 0; + else if (! NILP (process)) + nsecs = 0; return - (wait_reading_process_output (secs, usecs, 0, 0, + (wait_reading_process_output (secs, nsecs, 0, 0, Qnil, !NILP (process) ? XPROCESS (process) : NULL, NILP (just_this_one) ? 0 : @@ -4217,34 +4231,19 @@ wait_reading_process_output_1 (void) { } -/* Use a wrapper around select to work around a bug in gdb 5.3. - Normally, the wrapper is optimized away by inlining. - - If emacs is stopped inside select, the gdb backtrace doesn't - show the function which called select, so it is practically - impossible to step through wait_reading_process_output. */ - -#ifndef select -static inline int -select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tmo) -{ - return select (n, rfd, wfd, xfd, tmo); -} -#define select select_wrapper -#endif - /* Read and dispose of subprocess output while waiting for timeout to elapse and/or keyboard input to be available. TIME_LIMIT is: - timeout in seconds, or - zero for no limit, or - -1 means gobble data immediately available but don't wait for any. + timeout in seconds + If negative, gobble data immediately available but don't wait for any. - MICROSECS is: - an additional duration to wait, measured in microseconds. - If this is nonzero and time_limit is 0, then the timeout - consists of MICROSECS only. + NSECS is: + an additional duration to wait, measured in nanoseconds + If TIME_LIMIT is zero, then: + If NSECS == 0, there is no limit. + If NSECS > 0, the timeout consists of NSECS only. + If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative. READ_KBD is a lisp value: 0 to ignore keyboard input, or @@ -4271,7 +4270,7 @@ select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tm Otherwise, return true if we received input from any process. */ int -wait_reading_process_output (int time_limit, int microsecs, int read_kbd, +wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, int do_display, Lisp_Object wait_for_cell, struct Lisp_Process *wait_proc, int just_wait_proc) @@ -4291,7 +4290,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, FD_ZERO (&Available); FD_ZERO (&Writeok); - if (time_limit == 0 && microsecs == 0 && wait_proc && !NILP (Vinhibit_quit) + if (time_limit == 0 && nsecs == 0 && wait_proc && !NILP (Vinhibit_quit) && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit))) message ("Blocking call to accept-process-output with quit inhibited!!"); @@ -4303,12 +4302,20 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, make_number (waiting_for_user_input_p)); waiting_for_user_input_p = read_kbd; + if (time_limit < 0) + { + time_limit = 0; + nsecs = -1; + } + else if (TYPE_MAXIMUM (time_t) < time_limit) + time_limit = TYPE_MAXIMUM (time_t); + /* Since we may need to wait several times, compute the absolute time to return at. */ - if (time_limit || microsecs) + if (time_limit || nsecs) /* FIXME neither should be negative, no? */ { EMACS_GET_TIME (end_time); - EMACS_SET_SECS_USECS (timeout, time_limit, microsecs); + EMACS_SET_SECS_NSECS (timeout, time_limit, nsecs); EMACS_ADD_TIME (end_time, end_time, timeout); } @@ -4332,7 +4339,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, /* Compute time from now till when time limit is up */ /* Exit if already run out */ - if (time_limit == -1) + if (nsecs < 0) { /* -1 specified for timeout means gobble output available now @@ -4340,12 +4347,12 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, EMACS_SET_SECS_USECS (timeout, 0, 0); } - else if (time_limit || microsecs) + else if (time_limit || nsecs) { EMACS_GET_TIME (timeout); - EMACS_SUB_TIME (timeout, end_time, timeout); - if (EMACS_TIME_NEG_P (timeout)) + if (EMACS_TIME_LE (end_time, timeout)) break; + EMACS_SUB_TIME (timeout, end_time, timeout); } else { @@ -4391,21 +4398,22 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, && requeued_events_pending_p ()) break; - if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1) + /* If time_limit is negative, we are not going to wait at all. */ + if (0 <= nsecs) { - EMACS_TIME difference; - EMACS_SUB_TIME (difference, timer_delay, timeout); - if (EMACS_TIME_NEG_P (difference)) + if (EMACS_TIME_VALID_P (timer_delay)) { - timeout = timer_delay; - timeout_reduced_for_timers = 1; + if (EMACS_TIME_LT (timer_delay, timeout)) + { + timeout = timer_delay; + timeout_reduced_for_timers = 1; + } + } + else + { + /* This is so a breakpoint can be put here. */ + wait_reading_process_output_1 (); } - } - /* If time_limit is -1, we are not going to wait at all. */ - else if (time_limit != -1) - { - /* This is so a breakpoint can be put here. */ - wait_reading_process_output_1 (); } } @@ -4434,14 +4442,14 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, Ctemp = write_mask; EMACS_SET_SECS_USECS (timeout, 0, 0); - if ((select (max (max_process_desc, max_input_desc) + 1, - &Atemp, + if ((pselect (max (max_process_desc, max_input_desc) + 1, + &Atemp, #ifdef NON_BLOCKING_CONNECT - (num_pending_connects > 0 ? &Ctemp : (SELECT_TYPE *)0), + (num_pending_connects > 0 ? &Ctemp : NULL), #else - (SELECT_TYPE *)0, + NULL, #endif - (SELECT_TYPE *)0, &timeout) + NULL, &timeout, NULL) <= 0)) { /* It's okay for us to do this and then continue with @@ -4564,9 +4572,9 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, Vprocess_adaptive_read_buffering is nil. */ if (process_output_skip && check_delay > 0) { - int usecs = EMACS_USECS (timeout); - if (EMACS_SECS (timeout) > 0 || usecs > READ_OUTPUT_DELAY_MAX) - usecs = READ_OUTPUT_DELAY_MAX; + int nsecs = EMACS_NSECS (timeout); + if (EMACS_SECS (timeout) > 0 || nsecs > READ_OUTPUT_DELAY_MAX) + nsecs = READ_OUTPUT_DELAY_MAX; for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++) { proc = chan_process[channel]; @@ -4581,11 +4589,11 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, continue; FD_CLR (channel, &Available); XPROCESS (proc)->read_output_skip = 0; - if (XPROCESS (proc)->read_output_delay < usecs) - usecs = XPROCESS (proc)->read_output_delay; + if (XPROCESS (proc)->read_output_delay < nsecs) + nsecs = XPROCESS (proc)->read_output_delay; } } - EMACS_SET_SECS_USECS (timeout, 0, usecs); + EMACS_SET_SECS_NSECS (timeout, 0, nsecs); process_output_skip = 0; } #endif @@ -4594,27 +4602,58 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, #elif defined (HAVE_NS) nfds = ns_select #else - nfds = select + nfds = pselect #endif (max (max_process_desc, max_input_desc) + 1, &Available, (check_write ? &Writeok : (SELECT_TYPE *)0), - (SELECT_TYPE *)0, &timeout); + NULL, &timeout, NULL); #ifdef HAVE_GNUTLS /* GnuTLS buffers data internally. In lowat mode it leaves some data in the TCP buffers so that select works, but with custom pull/push functions we need to check if some data is available in the buffers manually. */ - if (nfds == 0 && - wait_proc && wait_proc->gnutls_p /* Check for valid process. */ - /* Do we have pending data? */ - && emacs_gnutls_record_check_pending (wait_proc->gnutls_state) > 0) - { - nfds = 1; - /* Set to Available. */ - FD_SET (wait_proc->infd, &Available); - } + if (nfds == 0) + { + if (! wait_proc) + { + /* We're not waiting on a specific process, so loop + through all the channels and check for data. + This is a workaround needed for some versions of + the gnutls library -- 2.12.14 has been confirmed + to need it. See + http://comments.gmane.org/gmane.emacs.devel/145074 */ + for (channel = 0; channel < MAXDESC; ++channel) + if (! NILP (chan_process[channel])) + { + struct Lisp_Process *p = + XPROCESS (chan_process[channel]); + if (p && p->gnutls_p && p->infd + && ((emacs_gnutls_record_check_pending + (p->gnutls_state)) + > 0)) + { + nfds++; + FD_SET (p->infd, &Available); + } + } + } + else + { + /* Check this specific channel. */ + if (wait_proc->gnutls_p /* Check for valid process. */ + /* Do we have pending data? */ + && ((emacs_gnutls_record_check_pending + (wait_proc->gnutls_state)) + > 0)) + { + nfds = 1; + /* Set to Available. */ + FD_SET (wait_proc->infd, &Available); + } + } + } #endif } @@ -4626,7 +4665,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, /* If we woke up due to SIGWINCH, actually change size now. */ do_pending_window_change (0); - if (time_limit && nfds == 0 && ! timeout_reduced_for_timers) + if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers) /* We wanted the full specified time, so return now. */ break; if (nfds < 0) @@ -4778,7 +4817,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, if (wait_channel == channel) { wait_channel = -1; - time_limit = -1; + nsecs = -1; got_some_input = 1; } proc = chan_process[channel]; @@ -4842,15 +4881,27 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, It can't hurt. */ else if (nread == -1 && errno == EIO) { - /* Clear the descriptor now, so we only raise the signal once. */ + struct Lisp_Process *p = XPROCESS (proc); + + /* Clear the descriptor now, so we only raise the + signal once. */ FD_CLR (channel, &input_wait_mask); FD_CLR (channel, &non_keyboard_wait_mask); - kill (getpid (), SIGCHLD); + if (p->pid == -2) + { + /* If the EIO occurs on a pty, sigchld_handler's + wait3() will not find the process object to + delete. Do it here. */ + p->tick = ++process_tick; + p->status = Qfailed; + } + else + kill (getpid (), SIGCHLD); } #endif /* HAVE_PTYS */ - /* If we can detect process termination, don't consider the process - gone just because its pipe is closed. */ + /* If we can detect process termination, don't consider the + process gone just because its pipe is closed. */ #ifdef SIGCHLD else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc)) ; @@ -5014,9 +5065,8 @@ read_process_output (Lisp_Object proc, register int channel) proc_buffered_char[channel] = -1; } #ifdef HAVE_GNUTLS - if (XPROCESS (proc)->gnutls_p) - nbytes = emacs_gnutls_read (XPROCESS (proc), - chars + carryover + buffered, + if (p->gnutls_p) + nbytes = emacs_gnutls_read (p, chars + carryover + buffered, readmax - buffered); else #endif @@ -5305,7 +5355,7 @@ static jmp_buf send_process_frame; static Lisp_Object process_sent_to; #ifndef FORWARD_SIGNAL_TO_MAIN_THREAD -static void send_process_trap (int) NO_RETURN; +static _Noreturn void send_process_trap (int); #endif static void @@ -5316,6 +5366,78 @@ send_process_trap (int ignore) longjmp (send_process_frame, 1); } +/* In send_process, when a write fails temporarily, + wait_reading_process_output is called. It may execute user code, + e.g. timers, that attempts to write new data to the same process. + We must ensure that data is sent in the right order, and not + interspersed half-completed with other writes (Bug#10815). This is + handled by the write_queue element of struct process. It is a list + with each entry having the form + + (string . (offset . length)) + + where STRING is a lisp string, OFFSET is the offset into the + string's byte sequence from which we should begin to send, and + LENGTH is the number of bytes left to send. */ + +/* Create a new entry in write_queue. + INPUT_OBJ should be a buffer, string Qt, or Qnil. + BUF is a pointer to the string sequence of the input_obj or a C + string in case of Qt or Qnil. */ + +static void +write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj, + const char *buf, ptrdiff_t len, int front) +{ + ptrdiff_t offset; + Lisp_Object entry, obj; + + if (STRINGP (input_obj)) + { + offset = buf - SSDATA (input_obj); + obj = input_obj; + } + else + { + offset = 0; + obj = make_unibyte_string (buf, len); + } + + entry = Fcons (obj, Fcons (make_number (offset), make_number (len))); + + if (front) + p->write_queue = Fcons (entry, p->write_queue); + else + p->write_queue = nconc2 (p->write_queue, Fcons (entry, Qnil)); +} + +/* Remove the first element in the write_queue of process P, put its + contents in OBJ, BUF and LEN, and return non-zero. If the + write_queue is empty, return zero. */ + +static int +write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj, + const char **buf, ptrdiff_t *len) +{ + Lisp_Object entry, offset_length; + ptrdiff_t offset; + + if (NILP (p->write_queue)) + return 0; + + entry = XCAR (p->write_queue); + p->write_queue = XCDR (p->write_queue); + + *obj = XCAR (entry); + offset_length = XCDR (entry); + + *len = XINT (XCDR (offset_length)); + offset = XINT (XCAR (offset_length)); + *buf = SSDATA (*obj) + offset; + + return 1; +} + /* Send some data to process PROC. BUF is the beginning of the data; LEN is the number of characters. OBJECT is the Lisp object that the data comes from. If OBJECT is @@ -5334,11 +5456,8 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, struct Lisp_Process *p = XPROCESS (proc); ssize_t rv; struct coding_system *coding; - struct gcpro gcpro1; void (*volatile old_sigpipe) (int); - GCPRO1 (object); - if (p->raw_status_new) update_status (p); if (! EQ (p->status, Qrun)) @@ -5363,8 +5482,8 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, sending a multibyte text, thus we must encode it by the original coding system specified for the current process. - Another reason we comming here is that the coding system - was just complemented and new one was returned by + Another reason we come here is that the coding system + was just complemented and a new one was returned by complement_process_encoding_system. */ setup_coding_system (p->encode_coding_system, coding); Vlast_coding_system_used = p->encode_coding_system; @@ -5373,6 +5492,7 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, } else { + coding->src_multibyte = 0; /* For sending a unibyte text, character code conversion should not take place but EOL conversion should. So, setup raw-text or one of the subsidiary if we have not yet done it. */ @@ -5449,22 +5569,37 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, if (!setjmp (send_process_frame)) { p = XPROCESS (proc); /* Repair any setjmp clobbering. */ - process_sent_to = proc; - while (len > 0) + + /* If there is already data in the write_queue, put the new data + in the back of queue. Otherwise, ignore it. */ + if (!NILP (p->write_queue)) + write_queue_push (p, object, buf, len, 0); + + do /* while !NILP (p->write_queue) */ { - ptrdiff_t this = len; + ptrdiff_t cur_len = -1; + const char *cur_buf; + Lisp_Object cur_object; - /* Send this batch, using one or more write calls. */ - while (this > 0) + /* If write_queue is empty, ignore it. */ + if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len)) { + cur_len = len; + cur_buf = buf; + cur_object = object; + } + + while (cur_len > 0) + { + /* Send this batch, using one or more write calls. */ ptrdiff_t written = 0; int outfd = p->outfd; old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap); #ifdef DATAGRAM_SOCKETS if (DATAGRAM_CHAN_P (outfd)) { - rv = sendto (outfd, buf, this, + rv = sendto (outfd, cur_buf, cur_len, 0, datagram_address[outfd].sa, datagram_address[outfd].len); if (0 <= rv) @@ -5480,12 +5615,11 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, #endif { #ifdef HAVE_GNUTLS - if (XPROCESS (proc)->gnutls_p) - written = emacs_gnutls_write (XPROCESS (proc), - buf, this); + if (p->gnutls_p) + written = emacs_gnutls_write (p, cur_buf, cur_len); else #endif - written = emacs_write (outfd, buf, this); + written = emacs_write (outfd, cur_buf, cur_len); rv = (written ? 0 : -1); #ifdef ADAPTIVE_READ_BUFFERING if (p->read_output_delay > 0 @@ -5513,8 +5647,6 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, that may allow the program to finish doing output and read more. */ { - ptrdiff_t offset = 0; - #ifdef BROKEN_PTY_READ_AFTER_EAGAIN /* A gross hack to work around a bug in FreeBSD. In the following sequence, read(2) returns @@ -5540,35 +5672,22 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, } #endif /* BROKEN_PTY_READ_AFTER_EAGAIN */ - /* Running filters might relocate buffers or strings. - Arrange to relocate BUF. */ - if (BUFFERP (object)) - offset = BUF_PTR_BYTE_POS (XBUFFER (object), - (unsigned char *) buf); - else if (STRINGP (object)) - offset = buf - SSDATA (object); - -#ifdef EMACS_HAS_USECS - wait_reading_process_output (0, 20000, 0, 0, Qnil, NULL, 0); -#else - wait_reading_process_output (1, 0, 0, 0, Qnil, NULL, 0); -#endif - - if (BUFFERP (object)) - buf = (char *) BUF_BYTE_ADDRESS (XBUFFER (object), - offset); - else if (STRINGP (object)) - buf = offset + SSDATA (object); + /* Put what we should have written in wait_queue. */ + write_queue_push (p, cur_object, cur_buf, cur_len, 1); + wait_reading_process_output (0, 20 * 1000 * 1000, + 0, 0, Qnil, NULL, 0); + /* Reread queue, to see what is left. */ + break; } else /* This is a real error. */ report_file_error ("writing to process", Fcons (proc, Qnil)); } - buf += written; - len -= written; - this -= written; + cur_buf += written; + cur_len -= written; } } + while (!NILP (p->write_queue)); } else { @@ -5581,8 +5700,6 @@ send_process (volatile Lisp_Object proc, const char *volatile buf, deactivate_process (proc); error ("SIGPIPE raised on process %s; closed it", SDATA (p->name)); } - - UNGCPRO; } DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region, @@ -6698,12 +6815,18 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, Wait for timeout to elapse and/or keyboard input to be available. - time_limit is: - timeout in seconds, or - zero for no limit, or - -1 means gobble data immediately available but don't wait for any. + TIME_LIMIT is: + timeout in seconds + If negative, gobble data immediately available but don't wait for any. + + NSECS is: + an additional duration to wait, measured in nanoseconds + If TIME_LIMIT is zero, then: + If NSECS == 0, there is no limit. + If NSECS > 0, the timeout consists of NSECS only. + If NSECS < 0, gobble data immediately, as if TIME_LIMIT were negative. - read_kbd is a Lisp_Object: + READ_KBD is a Lisp_Object: 0 to ignore keyboard input, or 1 to return when input is available, or -1 means caller will actually read the input, so don't throw to @@ -6712,13 +6835,13 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, see full version for other parameters. We know that wait_proc will always be NULL, since `subprocesses' isn't defined. - do_display != 0 means redisplay should be done to show subprocess + DO_DISPLAY != 0 means redisplay should be done to show subprocess output that arrives. Return true if we received input from any process. */ int -wait_reading_process_output (int time_limit, int microsecs, int read_kbd, +wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, int do_display, Lisp_Object wait_for_cell, struct Lisp_Process *wait_proc, int just_wait_proc) @@ -6728,11 +6851,19 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, SELECT_TYPE waitchannels; int xerrno; + if (time_limit < 0) + { + time_limit = 0; + nsecs = -1; + } + else if (TYPE_MAXIMUM (time_t) < time_limit) + time_limit = TYPE_MAXIMUM (time_t); + /* What does time_limit really mean? */ - if (time_limit || microsecs) + if (time_limit || nsecs) /* FIXME: what if negative? */ { EMACS_GET_TIME (end_time); - EMACS_SET_SECS_USECS (timeout, time_limit, microsecs); + EMACS_SET_SECS_NSECS (timeout, time_limit, nsecs); EMACS_ADD_TIME (end_time, end_time, timeout); } @@ -6758,7 +6889,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, /* Compute time from now till when time limit is up */ /* Exit if already run out */ - if (time_limit == -1) + if (nsecs < 0) { /* -1 specified for timeout means gobble output available now @@ -6766,12 +6897,12 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, EMACS_SET_SECS_USECS (timeout, 0, 0); } - else if (time_limit || microsecs) + else if (time_limit || nsecs) { EMACS_GET_TIME (timeout); - EMACS_SUB_TIME (timeout, end_time, timeout); - if (EMACS_TIME_NEG_P (timeout)) + if (EMACS_TIME_LE (end_time, timeout)) break; + EMACS_SUB_TIME (timeout, end_time, timeout); } else { @@ -6804,11 +6935,9 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, && requeued_events_pending_p ()) break; - if (! EMACS_TIME_NEG_P (timer_delay) && time_limit != -1) + if (EMACS_TIME_VALID_P (timer_delay) && 0 <= nsecs) { - EMACS_TIME difference; - EMACS_SUB_TIME (difference, timer_delay, timeout); - if (EMACS_TIME_NEG_P (difference)) + if (EMACS_TIME_LT (timer_delay, timeout)) { timeout = timer_delay; timeout_reduced_for_timers = 1; @@ -6844,8 +6973,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, FD_ZERO (&waitchannels); } else - nfds = select (1, &waitchannels, (SELECT_TYPE *)0, (SELECT_TYPE *)0, - &timeout); + nfds = pselect (1, &waitchannels, NULL, NULL, &timeout, NULL); xerrno = errno; @@ -6855,7 +6983,7 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd, /* If we woke up due to SIGWINCH, actually change size now. */ do_pending_window_change (0); - if (time_limit && nfds == 0 && ! timeout_reduced_for_timers) + if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers) /* We waited the full specified time, so return now. */ break; @@ -7158,19 +7286,20 @@ integer or floating point values. majflt -- number of major page faults (number) cminflt -- cumulative number of minor page faults (number) cmajflt -- cumulative number of major page faults (number) - utime -- user time used by the process, in the (HIGH LOW USEC) format - stime -- system time used by the process, in the (HIGH LOW USEC) format - time -- sum of utime and stime, in the (HIGH LOW USEC) format - cutime -- user time used by the process and its children, (HIGH LOW USEC) - cstime -- system time used by the process and its children, (HIGH LOW USEC) - ctime -- sum of cutime and cstime, in the (HIGH LOW USEC) format + utime -- user time used by the process, in (current-time) format, + which is a list of integers (HIGH LOW USEC PSEC) + stime -- system time used by the process (current-time) + time -- sum of utime and stime (current-time) + cutime -- user time used by the process and its children (current-time) + cstime -- system time used by the process and its children (current-time) + ctime -- sum of cutime and cstime (current-time) pri -- priority of the process (number) nice -- nice value of the process (number) thcount -- process thread count (number) - start -- time the process started, in the (HIGH LOW USEC) format + start -- time the process started (current-time) vsize -- virtual memory size of the process in KB's (number) rss -- resident set size of the process in KB's (number) - etime -- elapsed time the process is running, in (HIGH LOW USEC) format + etime -- elapsed time the process is running, in (HIGH LOW USEC PSEC) format pcpu -- percents of CPU time used by the process (floating-point number) pmem -- percents of total physical memory used by process's resident set (floating-point number) @@ -7395,7 +7524,7 @@ syms_of_process (void) DEFSYM (Qargs, "args"); DEFVAR_BOOL ("delete-exited-processes", delete_exited_processes, - doc: /* *Non-nil means delete processes immediately when they exit. + doc: /* Non-nil means delete processes immediately when they exit. A value of nil means don't delete them until `list-processes' is run. */); delete_exited_processes = 1;