When calling ossl_crypto_condvar_wait_timeout() we must use real time
authorMatt Caswell <matt@openssl.org>
Fri, 6 Oct 2023 14:56:15 +0000 (15:56 +0100)
committerMatt Caswell <matt@openssl.org>
Tue, 10 Oct 2023 07:17:43 +0000 (08:17 +0100)
Although many of the QUIC tests use fake time, the time we pass to the
ossl_crypto_condvar_wait_timeout() must be a real time.

Passing fake time was causing the QUIC tserver test to hang because
ossl_crypto_convar_wait_timeout() always timed out immediately and never
relinquished the CPU.

If using fake time we adjust the time to real time just before using it.

Fixes #22020

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/22301)

include/internal/quic_thread_assist.h
ssl/quic/quic_impl.c
ssl/quic/quic_thread_assist.c

index 7d1b47453a1549fddba9854e08418e82d5e78f94..592c2ffabffebda8200caf7cec4d6aa507264fe0 100644 (file)
@@ -12,6 +12,7 @@
 
 # include <openssl/ssl.h>
 # include "internal/thread.h"
+# include "internal/time.h"
 
 # if defined(OPENSSL_NO_QUIC) || defined(OPENSSL_NO_THREAD_POOL)
 #  define OPENSSL_NO_QUIC_THREAD_ASSIST
@@ -46,6 +47,8 @@ typedef struct quic_thread_assist_st {
     CRYPTO_CONDVAR *cv;
     CRYPTO_THREAD *t;
     int teardown, joined;
+    OSSL_TIME (*now_cb)(void *arg);
+    void *now_cb_arg;
 } QUIC_THREAD_ASSIST;
 
 /*
@@ -55,7 +58,9 @@ typedef struct quic_thread_assist_st {
  * not affect the state of the mutex.
  */
 int ossl_quic_thread_assist_init_start(QUIC_THREAD_ASSIST *qta,
-                                       QUIC_CHANNEL *ch);
+                                       QUIC_CHANNEL *ch,
+                                       OSSL_TIME (*now_cb)(void *arg),
+                                       void *now_cb_arg);
 
 /*
  * Request the thread assist helper to begin stopping the assist thread. This
index cb927fa52d131263af5ec8d9dedb7a4985b9321f..86020a450a99db0dc0182b64ade7383c80965c44 100644 (file)
@@ -1532,7 +1532,9 @@ static int ensure_channel_started(QCTX *ctx)
 
 #if !defined(OPENSSL_NO_QUIC_THREAD_ASSIST)
         if (qc->is_thread_assisted)
-            if (!ossl_quic_thread_assist_init_start(&qc->thread_assist, qc->ch)) {
+            if (!ossl_quic_thread_assist_init_start(&qc->thread_assist, qc->ch,
+                                                    qc->override_now_cb,
+                                                    qc->override_now_cb_arg)) {
                 QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR,
                                             "failed to start assist thread");
                 return 0;
index b5c1829e8e6012c50098e7f02aca710e9c38e9bd..e1de72a910a8112345ee1005ada524847daf2972 100644 (file)
@@ -28,11 +28,24 @@ static unsigned int assist_thread_main(void *arg)
     rtor = ossl_quic_channel_get_reactor(qta->ch);
 
     for (;;) {
+        OSSL_TIME deadline;
+
         if (qta->teardown)
             break;
 
-        ossl_crypto_condvar_wait_timeout(qta->cv, m,
-                                         ossl_quic_reactor_get_tick_deadline(rtor));
+        deadline = ossl_quic_reactor_get_tick_deadline(rtor);
+        if (qta->now_cb != NULL
+                && !ossl_time_is_zero(deadline)
+                && !ossl_time_is_infinite(deadline)) {
+            /*
+             * ossl_crypto_condvar_wait_timeout needs to use real time for the
+             * deadline
+             */
+            deadline = ossl_time_add(ossl_time_subtract(deadline,
+                                                        qta->now_cb(qta->now_cb_arg)),
+                                     ossl_time_now());
+        }
+        ossl_crypto_condvar_wait_timeout(qta->cv, m, deadline);
 
         /*
          * We have now been woken up. This can be for one of the following
@@ -56,7 +69,9 @@ static unsigned int assist_thread_main(void *arg)
 }
 
 int ossl_quic_thread_assist_init_start(QUIC_THREAD_ASSIST *qta,
-                                       QUIC_CHANNEL *ch)
+                                       QUIC_CHANNEL *ch,
+                                       OSSL_TIME (*now_cb)(void *arg),
+                                       void *now_cb_arg)
 {
     CRYPTO_MUTEX *mutex = ossl_quic_channel_get_mutex(ch);
 
@@ -66,6 +81,8 @@ int ossl_quic_thread_assist_init_start(QUIC_THREAD_ASSIST *qta,
     qta->ch         = ch;
     qta->teardown   = 0;
     qta->joined     = 0;
+    qta->now_cb     = now_cb;
+    qta->now_cb_arg = now_cb_arg;
 
     qta->cv = ossl_crypto_condvar_new();
     if (qta->cv == NULL)