X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9898bd0e5b0e51ce9040e11ae25c9a07ec08eb4f..f247498ead8b1898decf47537d59965340d6cebd:/src/process.c
diff --git a/src/process.c b/src/process.c
index 71da2e1767..f7ecd9b05a 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)
@@ -244,7 +249,6 @@ static int process_output_skip;
#define process_output_delay_count 0
#endif
-static Lisp_Object Fget_process (Lisp_Object);
static void create_process (Lisp_Object, char **, Lisp_Object);
#ifdef SIGIO
static int keyboard_bit_set (SELECT_TYPE *);
@@ -348,7 +352,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 +365,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 +382,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 +399,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 +624,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. */
@@ -1036,8 +1027,8 @@ DEFUN ("set-process-window-size", Fset_process_window_size,
(register Lisp_Object process, Lisp_Object height, Lisp_Object width)
{
CHECK_PROCESS (process);
- CHECK_RANGED_INTEGER (0, height, INT_MAX);
- CHECK_RANGED_INTEGER (0, width, INT_MAX);
+ CHECK_RANGED_INTEGER (height, 0, INT_MAX);
+ CHECK_RANGED_INTEGER (width, 0, INT_MAX);
if (XPROCESS (process)->infd < 0
|| set_window_size (XPROCESS (process)->infd,
@@ -1063,7 +1054,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 +1069,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);
@@ -1094,10 +1088,6 @@ DEFUN ("process-query-on-exit-flag",
return (XPROCESS (process)->kill_without_query ? Qnil : Qt);
}
-#ifdef DATAGRAM_SOCKETS
-static Lisp_Object Fprocess_datagram_address (Lisp_Object);
-#endif
-
DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
1, 2, 0,
doc: /* Return the contact info of PROCESS; t for a real child.
@@ -1375,7 +1365,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
val = Vcoding_system_for_read;
if (NILP (val))
{
- args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+ args2 = alloca ((nargs + 1) * sizeof *args2);
args2[0] = Qstart_process;
for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
GCPRO2 (proc, current_dir);
@@ -1394,7 +1384,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
{
if (EQ (coding_systems, Qt))
{
- args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+ args2 = alloca ((nargs + 1) * sizeof *args2);
args2[0] = Qstart_process;
for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
GCPRO2 (proc, current_dir);
@@ -1408,7 +1398,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
@@ -1488,7 +1478,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
/* Now that everything is encoded we can collect the strings into
NEW_ARGV. */
- new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
+ new_argv = alloca ((nargs - 1) * sizeof *new_argv);
new_argv[nargs - 2] = 0;
for (i = nargs - 2; i-- != 0; )
@@ -1515,8 +1505,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 +2508,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 +2537,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 +2776,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.
@@ -3277,7 +3267,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 +3275,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)
@@ -3327,7 +3316,7 @@ usage: (make-network-process &rest ARGS) */)
{
if (datagram_address[s].sa)
abort ();
- datagram_address[s].sa = (struct sockaddr *) xmalloc (lres->ai_addrlen);
+ datagram_address[s].sa = xmalloc (lres->ai_addrlen);
datagram_address[s].len = lres->ai_addrlen;
if (is_server)
{
@@ -3470,7 +3459,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 +3476,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 +3487,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 +3520,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 +3702,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 +3936,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 +3956,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 +4226,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 +4265,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 +4285,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 +4297,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 || 0 < nsecs)
{
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,20 +4334,20 @@ 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
+ /* A negative timeout means
gobble output available now
but don't wait at all. */
EMACS_SET_SECS_USECS (timeout, 0, 0);
}
- else if (time_limit || microsecs)
+ else if (time_limit || 0 < 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 +4393,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)
+ /* A negative timeout means do not 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 +4437,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 +4567,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 +4584,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 +4597,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,8 +4660,8 @@ 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)
- /* We wanted the full specified time, so return now. */
+ if ((time_limit || nsecs) && nfds == 0 && ! timeout_reduced_for_timers)
+ /* We waited the full specified time, so return now. */
break;
if (nfds < 0)
{
@@ -4778,7 +4812,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 +4876,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))
;
@@ -4991,7 +5037,7 @@ read_process_output (Lisp_Object proc, register int channel)
ptrdiff_t count = SPECPDL_INDEX ();
Lisp_Object odeactivate;
- chars = (char *) alloca (carryover + readmax);
+ chars = alloca (carryover + readmax);
if (carryover)
/* See the comment above. */
memcpy (chars, SDATA (p->decoding_buf), carryover);
@@ -5014,9 +5060,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 +5350,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 +5361,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 +5451,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))
@@ -5450,22 +5564,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)
@@ -5481,12 +5610,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
@@ -5514,8 +5642,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
@@ -5541,35 +5667,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
{
@@ -5582,8 +5695,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,
@@ -6175,7 +6286,7 @@ process has been transmitted to the serial port. */)
if (!proc_encode_coding_system[new_outfd])
proc_encode_coding_system[new_outfd]
- = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+ = xmalloc (sizeof (struct coding_system));
memcpy (proc_encode_coding_system[new_outfd],
proc_encode_coding_system[old_outfd],
sizeof (struct coding_system));
@@ -6692,19 +6803,25 @@ keyboard_bit_set (fd_set *mask)
/* Defined on msdos.c. */
extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
- EMACS_TIME *);
+ EMACS_TIME *, void *);
/* Implementation of wait_reading_process_output, assuming that there
are no subprocesses. Used only by the MS-DOS build.
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
@@ -6713,13 +6830,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)
@@ -6729,11 +6846,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 || 0 < nsecs)
{
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);
}
@@ -6759,20 +6884,20 @@ 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
+ /* A negative timeout means
gobble output available now
but don't wait at all. */
EMACS_SET_SECS_USECS (timeout, 0, 0);
}
- else if (time_limit || microsecs)
+ else if (time_limit || 0 < 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
{
@@ -6805,11 +6930,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;
@@ -6845,8 +6968,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;
@@ -6856,7 +6978,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;
@@ -6961,8 +7083,7 @@ setup_process_coding_systems (Lisp_Object process)
return;
if (!proc_decode_coding_system[inch])
- proc_decode_coding_system[inch]
- = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+ proc_decode_coding_system[inch] = xmalloc (sizeof (struct coding_system));
coding_system = p->decode_coding_system;
if (! NILP (p->filter))
;
@@ -6974,8 +7095,7 @@ setup_process_coding_systems (Lisp_Object process)
setup_coding_system (coding_system, proc_decode_coding_system[inch]);
if (!proc_encode_coding_system[outch])
- proc_encode_coding_system[outch]
- = (struct coding_system *) xmalloc (sizeof (struct coding_system));
+ proc_encode_coding_system[outch] = xmalloc (sizeof (struct coding_system));
setup_coding_system (p->encode_coding_system,
proc_encode_coding_system[outch]);
#endif
@@ -7159,19 +7279,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)
@@ -7396,7 +7517,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;