summaryrefslogtreecommitdiff
path: root/src/process.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2019-01-15 23:51:45 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2019-01-15 23:52:47 -0800
commite87e6a24c49542111e669b7d0f1a412024663f8e (patch)
treeba382d326874795c7b131a7995c67e660650a80c /src/process.c
parent6b9fa8804533a695094a930d634d2d6617e2b6c7 (diff)
downloademacs-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.c28
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)