From 02d62978f46fcc2793608bb57a2c20a30555dbba Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sat, 24 Apr 2021 17:59:14 +0200 Subject: http-client, substitute: Gracefully handle GnuTLS EAGAIN/EINTR. Partly fixes . Reported by Florian Pelz . 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. --- guix/http-client.scm | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'guix/http-client.scm') diff --git a/guix/http-client.scm b/guix/http-client.scm index a2e11a1b73..bb1b0eeb56 100644 --- a/guix/http-client.scm +++ b/guix/http-client.scm @@ -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 + ;; . + error/again error/interrupted))) (memq key '(bad-response bad-header bad-header-component))) #f -- cgit v1.2.3 From c50db7156dfdd5dc126d7812cf4f51903bfa4599 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sat, 24 Apr 2021 18:07:09 +0200 Subject: http-client: Remove exception mishandling in 'http-multiple-get'. Partly fixes . Reported by Florian Pelz . The non-tail recursive call to 'connect' could cause requests to be processed twice, with 'p' possibly closed the second time. Regression introduced in 205833b72c5517915a47a50dbe28e7024dc74e57 and carried over in 45fce38fb0b6c6796906149ade145b8d3594c1c6. * guix/http-client.scm (http-multiple-get): Remove call to 'close-port' and recursive call to 'connect' when the 'write-request' block returns #f. --- guix/http-client.scm | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'guix/http-client.scm') diff --git a/guix/http-client.scm b/guix/http-client.scm index bb1b0eeb56..10bc278023 100644 --- a/guix/http-client.scm +++ b/guix/http-client.scm @@ -214,15 +214,14 @@ returning." ;; Inherit the HTTP proxying property from P. (set-http-proxy-port?! buffer (http-proxy-port? p)) - (unless (false-if-networking-error - (begin - (for-each (cut write-request <> buffer) batch) - (put-bytevector p (get)) - (force-output p) - #t)) - ;; If PORT becomes unusable, open a fresh connection and retry. - (close-port p) ; close the broken port - (connect #f requests result))) + ;; Swallow networking errors that could occur due to connection reuse + ;; and the like; they will be handled down the road when trying to + ;; read responses. + (false-if-networking-error + (begin + (for-each (cut write-request <> buffer) batch) + (put-bytevector p (get)) + (force-output p)))) ;; Now start processing responses. (let loop ((sent batch) -- cgit v1.2.3