diff options
| author | Paul Eggert <eggert@cs.ucla.edu> | 2019-01-15 23:51:45 -0800 |
|---|---|---|
| committer | Paul Eggert <eggert@cs.ucla.edu> | 2019-01-15 23:52:47 -0800 |
| commit | e87e6a24c49542111e669b7d0f1a412024663f8e (patch) | |
| tree | ba382d326874795c7b131a7995c67e660650a80c /src/process.c | |
| parent | 6b9fa8804533a695094a930d634d2d6617e2b6c7 (diff) | |
| download | emacs-e87e6a24c49542111e669b7d0f1a412024663f8e.tar.gz | |
Fix unlikely races with GnuTLS, datagrams
Retry some calls if interrupted at inopportune times.
These were found by code inspection.
* src/gnutls.c (gnutls_try_handshake): Simplify by using
new emacs_gnutls_handle_error API.
(emacs_gnutls_write): Remove GNUTLS_E_AGAIN hack since
emacs_gnutls_handle_error now does that.
Use emacs_gnutls_handle_error only on errors.
(emacs_gnutls_read): Retry if gnutls_record_recv returns
GNUTLS_E_INTERRUPTED, to be consistent with emacs_read.
(emacs_gnutls_handle_error): Return 0 on fatal errors,
-1 (setting errno) on ordinary errors, to simplify callers.
Assume that ERR is negative, since it always is now.
Map non-fatal GnuTLS errors to errno values as best we can.
* src/process.c (read_process_output) [DATAGRAM_SOCKETS]:
Retry recvfrom if it is interrupted, to be consistent with
how things are handled when not a datagram channel.
(send_process) [DATAGRAM_SOCEKTS]: If sendto is interrupted,
process pending signals and retry it, to be consistent with
how things are handled when not a datagram channel.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/src/process.c b/src/process.c index 06555bac4c0..c0741403b57 100644 --- a/src/process.c +++ b/src/process.c @@ -5840,7 +5840,8 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars, /* Read pending output from the process channel, starting with our buffered-ahead character if we have one. - Yield number of decoded characters read. + Yield number of decoded characters read, + or -1 (setting errno) if there is a read error. This function reads at most 4096 characters. If you want to read all available subprocess output, @@ -5870,8 +5871,10 @@ read_process_output (Lisp_Object proc, int channel) if (DATAGRAM_CHAN_P (channel)) { socklen_t len = datagram_address[channel].len; - nbytes = recvfrom (channel, chars + carryover, readmax, - 0, datagram_address[channel].sa, &len); + do + nbytes = recvfrom (channel, chars + carryover, readmax, + 0, datagram_address[channel].sa, &len); + while (nbytes < 0 && errno == EINTR); } else #endif @@ -5921,8 +5924,6 @@ read_process_output (Lisp_Object proc, int channel) p->decoding_carryover = 0; - /* At this point, NBYTES holds number of bytes just received - (including the one in proc_buffered_char[channel]). */ if (nbytes <= 0) { if (nbytes < 0 || coding->mode & CODING_MODE_LAST_BLOCK) @@ -5930,6 +5931,9 @@ read_process_output (Lisp_Object proc, int channel) coding->mode |= CODING_MODE_LAST_BLOCK; } + /* At this point, NBYTES holds number of bytes just received + (including the one in proc_buffered_char[channel]). */ + /* Ignore carryover, it's been added by a previous iteration already. */ p->nbytes_read += nbytes; @@ -6372,9 +6376,17 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len, #ifdef DATAGRAM_SOCKETS if (DATAGRAM_CHAN_P (outfd)) { - rv = sendto (outfd, cur_buf, cur_len, - 0, datagram_address[outfd].sa, - datagram_address[outfd].len); + while (true) + { + rv = sendto (outfd, cur_buf, cur_len, 0, + datagram_address[outfd].sa, + datagram_address[outfd].len); + if (! (rv < 0 && errno == EINTR)) + break; + if (pending_signals) + process_pending_signals (); + } + if (rv >= 0) written = rv; else if (errno == EMSGSIZE) |
