aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c97
1 files changed, 46 insertions, 51 deletions
diff --git a/src/process.c b/src/process.c
index 6e5bcf307ab..15634e4a8b0 100644
--- a/src/process.c
+++ b/src/process.c
@@ -5491,6 +5491,10 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5491 } 5491 }
5492 else 5492 else
5493 { 5493 {
5494#ifdef HAVE_GNUTLS
5495 int tls_nfds;
5496 fd_set tls_available;
5497#endif
5494 /* Set the timeout for adaptive read buffering if any 5498 /* Set the timeout for adaptive read buffering if any
5495 process has non-zero read_output_skip and non-zero 5499 process has non-zero read_output_skip and non-zero
5496 read_output_delay, and we are not reading output for a 5500 read_output_delay, and we are not reading output for a
@@ -5560,7 +5564,36 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5560 } 5564 }
5561#endif 5565#endif
5562 5566
5563/* Non-macOS HAVE_GLIB builds call thread_select in xgselect.c. */ 5567#ifdef HAVE_GNUTLS
5568 /* GnuTLS buffers data internally. We need to check if some
5569 data is available in the buffers manually before the select.
5570 And if so, we need to skip the select which could block. */
5571 FD_ZERO (&tls_available);
5572 tls_nfds = 0;
5573 for (channel = 0; channel < FD_SETSIZE; ++channel)
5574 if (! NILP (chan_process[channel])
5575 && FD_ISSET (channel, &Available))
5576 {
5577 struct Lisp_Process *p = XPROCESS (chan_process[channel]);
5578 if (p
5579 && p->gnutls_p && p->gnutls_state
5580 && emacs_gnutls_record_check_pending (p->gnutls_state) > 0)
5581 {
5582 tls_nfds++;
5583 eassert (p->infd == channel);
5584 FD_SET (p->infd, &tls_available);
5585 }
5586 }
5587 /* If wait_proc is somebody else, we have to wait in select
5588 as usual. Otherwise, clobber the timeout. */
5589 if (tls_nfds > 0
5590 && (!wait_proc ||
5591 (wait_proc->infd >= 0
5592 && FD_ISSET (wait_proc->infd, &tls_available))))
5593 timeout = make_timespec (0, 0);
5594#endif
5595
5596 /* Non-macOS HAVE_GLIB builds call thread_select in xgselect.c. */
5564#if defined HAVE_GLIB && !defined HAVE_NS 5597#if defined HAVE_GLIB && !defined HAVE_NS
5565 nfds = xg_select (max_desc + 1, 5598 nfds = xg_select (max_desc + 1,
5566 &Available, (check_write ? &Writeok : 0), 5599 &Available, (check_write ? &Writeok : 0),
@@ -5578,59 +5611,21 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5578#endif /* !HAVE_GLIB */ 5611#endif /* !HAVE_GLIB */
5579 5612
5580#ifdef HAVE_GNUTLS 5613#ifdef HAVE_GNUTLS
5581 /* GnuTLS buffers data internally. In lowat mode it leaves 5614 /* Merge tls_available into Available. */
5582 some data in the TCP buffers so that select works, but 5615 if (tls_nfds > 0)
5583 with custom pull/push functions we need to check if some
5584 data is available in the buffers manually. */
5585 if (nfds == 0)
5586 { 5616 {
5587 fd_set tls_available; 5617 if (nfds == 0 || (nfds < 0 && errno == EINTR))
5588 int set = 0;
5589
5590 FD_ZERO (&tls_available);
5591 if (! wait_proc)
5592 { 5618 {
5593 /* We're not waiting on a specific process, so loop 5619 /* Fast path, just copy. */
5594 through all the channels and check for data. 5620 nfds = tls_nfds;
5595 This is a workaround needed for some versions of 5621 Available = tls_available;
5596 the gnutls library -- 2.12.14 has been confirmed
5597 to need it. */
5598 for (channel = 0; channel < FD_SETSIZE; ++channel)
5599 if (! NILP (chan_process[channel]))
5600 {
5601 struct Lisp_Process *p =
5602 XPROCESS (chan_process[channel]);
5603 if (p && p->gnutls_p && p->gnutls_state
5604 && ((emacs_gnutls_record_check_pending
5605 (p->gnutls_state))
5606 > 0))
5607 {
5608 nfds++;
5609 eassert (p->infd == channel);
5610 FD_SET (p->infd, &tls_available);
5611 set++;
5612 }
5613 }
5614 }
5615 else
5616 {
5617 /* Check this specific channel. */
5618 if (wait_proc->gnutls_p /* Check for valid process. */
5619 && wait_proc->gnutls_state
5620 /* Do we have pending data? */
5621 && ((emacs_gnutls_record_check_pending
5622 (wait_proc->gnutls_state))
5623 > 0))
5624 {
5625 nfds = 1;
5626 eassert (0 <= wait_proc->infd);
5627 /* Set to Available. */
5628 FD_SET (wait_proc->infd, &tls_available);
5629 set++;
5630 }
5631 } 5622 }
5632 if (set) 5623 else if (nfds > 0)
5633 Available = tls_available; 5624 /* Slow path, merge one by one. Note: nfds does not need
5625 to be accurate, just positive is enough. */
5626 for (channel = 0; channel < FD_SETSIZE; ++channel)
5627 if (FD_ISSET(channel, &tls_available))
5628 FD_SET(channel, &Available);
5634 } 5629 }
5635#endif 5630#endif
5636 } 5631 }