libnbd has long used MSG_NOSIGNAL to avoid receiving SIGPIPE if we
accidentally write on a closed socket, which is a nice alternative to
using a SIGPIPE signal handler. However with TLS connections, gnutls
did not use this flag and so programs using libnbd + TLS would receive
SIGPIPE in some situations, notably if the server closed the
connection abruptly while we were trying to write something.
GnuTLS 3.4.2 introduces GNUTLS_NO_SIGNAL which does the same thing.
Use this flag if available.
RHEL 7 has an older gnutls which lacks this flag. To avoid qemu-nbd
interop tests failing (rarely, but more often with a forthcoming
change to TLS shutdown behaviour), register a SIGPIPE signal handler
in the test if the flag is missing.
---
interop/interop.c | 8 ++++++++
lib/crypto.c | 7 ++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/interop/interop.c b/interop/interop.c
index f3437d7dea..bd5dc2e196 100644
--- a/interop/interop.c
+++ b/interop/interop.c
@@ -84,6 +84,14 @@ main (int argc, char *argv[])
REQUIRES
#endif
+ /* Ignore SIGPIPE. We only need this for GnuTLS that lacks the
+ * GNUTLS_NO_SIGNAL flag, either because it predates GnuTLS 3.4.2 or
+ * because the OS lacks MSG_NOSIGNAL support.
+ */
+#if TLS && !defined(HAVE_GNUTLS_NO_SIGNAL)
+ signal (SIGPIPE, SIG_IGN);
+#endif
+
/* Create a large sparse temporary file. */
#ifdef NEEDS_TMPFILE
int fd = mkstemp (TMPFILE);
diff --git a/lib/crypto.c b/lib/crypto.c
index 9d6332c6c9..7ff83c2314 100644
--- a/lib/crypto.c
+++ b/lib/crypto.c
@@ -606,8 +606,13 @@ nbd_internal_crypto_create_session (struct nbd_handle *h,
gnutls_session_t session;
gnutls_psk_client_credentials_t pskcreds = NULL;
gnutls_certificate_credentials_t xcreds = NULL;
+ gnutls_init_flags_t init_flags;
- err = gnutls_init (&session, GNUTLS_CLIENT|GNUTLS_NONBLOCK);
+ init_flags = GNUTLS_CLIENT | GNUTLS_NONBLOCK;
+#ifdef GNUTLS_NO_SIGNAL
+ init_flags |= GNUTLS_NO_SIGNAL;
+#endif
+ err = gnutls_init (&session, init_flags);
if (err < 0) {
set_error (errno, "gnutls_init: %s", gnutls_strerror (err));
return NULL;
--
2.37.0.rc2