summary refs log tree commit diff
path: root/gnu/packages/patches/gnutls-guile-eintr-eagain.patch
blob: e04c9451581d14336f440ee3a16b2fa2155b093e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Fixes <https://issues.guix.gnu.org/47867>.

This fix was merged upstream
in <https://gitlab.com/gnutls/gnutls/-/merge_requests/1417> and will
be in GnuTLS 3.7.3.  Upstream commit:

commit 110e2172dbef1fbdf7399dab1e80780847b61c0c
Author: Ludovic Courtès <ludo@gnu.org>
Date:   Sat Apr 24 22:02:14 2021 +0200

    guile: Writes to record ports handle EAGAIN/EINTR transparently.

diff --git a/guile/src/core.c b/guile/src/core.c
index a13670fc7b..0926dc8a97 100644
--- a/guile/src/core.c
+++ b/guile/src/core.c
@@ -985,7 +985,10 @@ write_to_session_record_port (SCM port, const void *data, size_t size)
       c_result = gnutls_record_send (c_session, (char *) data + c_sent,
                                      size - c_sent);
       if (EXPECT_FALSE (c_result < 0))
-        scm_gnutls_error (c_result, FUNC_NAME);
+	{
+	  if (c_result != GNUTLS_E_AGAIN && c_result != GNUTLS_E_INTERRUPTED)
+	    scm_gnutls_error (c_result, FUNC_NAME);
+	}
       else
         c_sent += c_result;
     }
@@ -1069,7 +1072,8 @@ read_from_session_record_port (SCM port, SCM dst, size_t start, size_t count)
 #undef FUNC_NAME
 
 /* Return the file descriptor that backs PORT.  This function is called upon a
-   blocking read--i.e., 'read_from_session_record_port' returned -1.  */
+   blocking read--i.e., 'read_from_session_record_port' or
+   'write_to_session_record_port' returned -1.  */
 static int
 session_record_port_fd (SCM port)
 {
@@ -1097,7 +1101,16 @@ write_to_session_record_port (SCM port, SCM src, size_t start, size_t count)
   c_session = scm_to_gnutls_session (session, 1, FUNC_NAME);
   data = (char *) SCM_BYTEVECTOR_CONTENTS (src) + start;
 
-  result = gnutls_record_send (c_session, data, count);
+  do
+    result = gnutls_record_send (c_session, data, count);
+  while (result == GNUTLS_E_INTERRUPTED
+	 || (result == GNUTLS_E_AGAIN
+	     && !SCM_GNUTLS_SESSION_TRANSPORT_IS_FD (c_session)));
+
+  if (result == GNUTLS_E_AGAIN
+      && SCM_GNUTLS_SESSION_TRANSPORT_IS_FD (c_session))
+    /* Tell Guile that reading would block.  */
+    return (size_t) -1;
 
   if (EXPECT_FALSE (result < 0))
     scm_gnutls_error (result, FUNC_NAME);