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