From c9fb65b8c8b82a8aa60a118342ec4ee58352db89 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 1 Aug 2023 12:22:58 +0100 Subject: [PATCH] Add support into qtest_shutdown for blocking mode Reviewed-by: Tomas Mraz Reviewed-by: Hugo Landau (Merged from https://github.com/openssl/openssl/pull/21591) --- test/helpers/quictestlib.c | 64 +++++++++++++++++++++++++++++++++++--- test/quicapitest.c | 17 ++-------- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index d081b121e8..8f28dfb898 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -20,6 +20,7 @@ #include "internal/quic_record_tx.h" #include "internal/quic_error.h" #include "internal/packet.h" +#include "internal/tsan_assist.h" #define GROWTH_ALLOWANCE 1024 @@ -338,22 +339,77 @@ int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl) return ret; } +#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) +static TSAN_QUALIFIER int shutdowndone; + +static void run_server_shutdown_thread(void) +{ + /* + * This will operate in a busy loop because the server does not block, + * but should be acceptable because it is local and we expect this to be + * fast + */ + do { + ossl_quic_tserver_tick(globtserv); + } while(!tsan_load(&shutdowndone)); +} +#endif + int qtest_shutdown(QUIC_TSERVER *qtserv, SSL *clientssl) { + int tickserver = 1; + int ret = 0; +#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) + /* + * Pointless initialisation to avoid bogus compiler warnings about using + * t uninitialised + */ + thread_t t = thread_zero; +#endif + + if (SSL_get_blocking_mode(clientssl) > 0) { +#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) + /* + * clientssl is blocking. We will need a thread to complete the + * connection + */ + globtserv = qtserv; + shutdowndone = 0; + if (!TEST_true(run_thread(&t, run_server_shutdown_thread))) + return 0; + + tickserver = 0; +#else + TEST_error("No thread support in this build"); + return 0; +#endif + } + /* Busy loop in non-blocking mode. It should be quick because its local */ for (;;) { int rc = SSL_shutdown(clientssl); - if (rc == 1) + if (rc == 1) { + ret = 1; break; + } if (rc < 0) - return 0; + break; - ossl_quic_tserver_tick(qtserv); + if (tickserver) + ossl_quic_tserver_tick(qtserv); } - return 1; +#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) + tsan_store(&shutdowndone, 1); + if (!tickserver) { + if (!TEST_true(wait_for_thread(t))) + ret = 0; + } +#endif + + return ret; } int qtest_check_server_transport_err(QUIC_TSERVER *qtserv, uint64_t code) diff --git a/test/quicapitest.c b/test/quicapitest.c index 3267b1b283..c694988d83 100644 --- a/test/quicapitest.c +++ b/test/quicapitest.c @@ -164,21 +164,8 @@ static int test_quic_write_read(int idx) goto end; } - if (idx < 1) { - /* - * Blocking SSL_shutdown cannot be tested here due to requirement to - * tick TSERVER during drainage. - */ - if (!TEST_true(qtest_shutdown(qtserv, clientquic))) - goto end; - } else { - /* - * We cheat here because we have not shutdown correctly. We make the - * client think it has been shutdown normally so the session is - * eligible for reuse. - */ - SSL_CONNECTION_FROM_SSL(clientquic)->shutdown = SSL_SENT_SHUTDOWN; - } + if (!TEST_true(qtest_shutdown(qtserv, clientquic))) + goto end; if (sctx == NULL) { sctx = ossl_quic_tserver_get0_ssl_ctx(qtserv);