http-client, substitute: Gracefully handle GnuTLS EAGAIN/EINTR.

Partly fixes <https://bugs.gnu.org/47867>.
Reported by Florian Pelz <pelzflorian@pelzflorian.de>.

In GnuTLS up to 3.7.1 included, GNUTLS_E_AGAIN and GNUTLS_E_INTERRUPTED
are not handled by 'write_to_session_record_port' and could be thrown at
the caller.  This patch works around that by dropping connections
altogether and restarting when this happens.

* guix/http-client.scm (false-if-networking-error): Swallow ERROR/AGAIN
and ERROR/INTERRUPTED.
* guix/scripts/substitute.scm (call-with-cached-connection): Likewise.
This commit is contained in:
Ludovic Courtès 2021-04-24 17:59:14 +02:00
parent f06685a985
commit 69ffe875c3
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
2 changed files with 18 additions and 4 deletions

@ -38,7 +38,7 @@
#:use-module (guix utils)
#:use-module (guix base64)
#:autoload (gcrypt hash) (sha256)
#:autoload (gnutls) (error/invalid-session)
#:autoload (gnutls) (error/invalid-session error/again error/interrupted)
#:use-module ((guix build utils)
#:select (mkdir-p dump-port))
#:use-module ((guix build download)
@ -163,7 +163,14 @@ reusing stale cached connections."
(if (or (and (eq? key 'system-error)
(= EPIPE (system-error-errno `(,key ,@args))))
(and (eq? key 'gnutls-error)
(eq? (first args) error/invalid-session))
(memq (first args)
(list error/invalid-session
;; XXX: These two are not properly handled in
;; GnuTLS < 3.7.2, in
;; 'write_to_session_record_port'; see
;; <https://bugs.gnu.org/47867>.
error/again error/interrupted)))
(memq key
'(bad-response bad-header bad-header-component)))
#f

@ -45,7 +45,7 @@
#:select (uri-abbreviation nar-uri-abbreviation
(open-connection-for-uri
. guix:open-connection-for-uri)))
#:autoload (gnutls) (error/invalid-session)
#:autoload (gnutls) (error/invalid-session error/again error/interrupted)
#:use-module (guix progress)
#:use-module ((guix build syscalls)
#:select (set-thread-name))
@ -417,7 +417,14 @@ server certificates."
(if (or (and (eq? key 'system-error)
(= EPIPE (system-error-errno `(,key ,@args))))
(and (eq? key 'gnutls-error)
(eq? (first args) error/invalid-session))
(memq (first args)
(list error/invalid-session
;; XXX: These two are not properly handled in
;; GnuTLS < 3.7.2, in
;; 'write_to_session_record_port'; see
;; <https://bugs.gnu.org/47867>.
error/again error/interrupted)))
(memq key '(bad-response bad-header bad-header-component)))
(proc (open-connection-for-uri/cached uri
#:verify-certificate? #f