]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
QUIC MSMT: Revise tests to support multithreading
authorHugo Landau <hlandau@openssl.org>
Fri, 28 Apr 2023 15:56:33 +0000 (16:56 +0100)
committerHugo Landau <hlandau@openssl.org>
Wed, 24 May 2023 09:34:47 +0000 (10:34 +0100)
Alsoo rename OPK_C_ACCEPT_STREAM to reflect its current behaviour.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20856)

test/quic_multistream_test.c

index 2fd8a2235f9f80e04134ffdf2e7de13a0f80f40e..1da6ef31fe5c84d5d56aff7c1425f7951eacdf78 100644 (file)
 #include "internal/quic_tserver.h"
 #include "internal/quic_ssl.h"
 #include "testutil.h"
+#if defined(OPENSSL_THREADS)
+# include "internal/thread_arch.h"
+#endif
 
 static const char *certfile, *keyfile;
 
+#if defined(OPENSSL_THREADS)
+struct child_thread_args {
+    struct helper *h;
+    const struct script_op *script;
+    int thread_idx;
+
+    CRYPTO_THREAD *t;
+    CRYPTO_MUTEX *m;
+    int testresult;
+    int done;
+};
+#endif
+
 typedef struct stream_info {
     const char      *name;
     SSL             *c_stream;
@@ -37,11 +53,22 @@ struct helper {
     SSL                     *c_conn;
     LHASH_OF(STREAM_INFO)   *c_streams;
 
+#if defined(OPENSSL_THREADS)
+    struct child_thread_args    *threads;
+    size_t                      num_threads;
+#endif
+
     OSSL_TIME       start_time;
     int             init, blocking, check_spin_again;
     int             free_order;
 };
 
+struct helper_local {
+    struct helper           *h;
+    LHASH_OF(STREAM_INFO)   *c_streams;
+    int                     thread_idx;
+};
+
 struct script_op {
     uint32_t        op;
     const void      *arg0;
@@ -67,7 +94,7 @@ struct script_op {
 #define OPK_C_ATTACH                                13
 #define OPK_C_NEW_STREAM                            14
 #define OPK_S_NEW_STREAM                            15
-#define OPK_C_ACCEPT_STREAM                         16
+#define OPK_C_ACCEPT_STREAM_WAIT                    16
 #define OPK_C_ACCEPT_STREAM_NONE                    17
 #define OPK_C_FREE_STREAM                           18
 #define OPK_C_SET_DEFAULT_STREAM_MODE               19
@@ -81,6 +108,8 @@ struct script_op {
 #define OPK_S_WRITE_FAIL                            27
 #define OPK_C_READ_FAIL                             28
 #define OPK_C_STREAM_RESET                          29
+#define OPK_S_ACCEPT_STREAM_WAIT                    30
+#define OPK_NEW_THREAD                              31
 
 #define EXPECT_CONN_CLOSE_APP       (1U << 0)
 #define EXPECT_CONN_CLOSE_REMOTE    (1U << 1)
@@ -94,6 +123,8 @@ struct script_op {
 #define S_UNI_ID(ordinal) \
     (((ordinal) << 2) | QUIC_STREAM_INITIATOR_SERVER | QUIC_STREAM_DIR_UNI)
 
+#define ANY_ID UINT64_MAX
+
 #define OP_END  \
     {OPK_END}
 #define OP_CHECK(func, arg2)  \
@@ -130,8 +161,8 @@ struct script_op {
     {OPK_S_NEW_STREAM, NULL, 0, NULL, #stream_name, (expect_id)},
 #define OP_S_NEW_STREAM_UNI(stream_name, expect_id) \
     {OPK_S_NEW_STREAM, NULL, 1, NULL, #stream_name, (expect_id)},
-#define OP_C_ACCEPT_STREAM(stream_name) \
-    {OPK_C_ACCEPT_STREAM, NULL, 0, NULL, #stream_name},
+#define OP_C_ACCEPT_STREAM_WAIT(stream_name) \
+    {OPK_C_ACCEPT_STREAM_WAIT, NULL, 0, NULL, #stream_name},
 #define OP_C_ACCEPT_STREAM_NONE() \
     {OPK_C_ACCEPT_STREAM_NONE, NULL, 0, NULL, NULL},
 #define OP_C_FREE_STREAM(stream_name) \
@@ -164,6 +195,10 @@ struct script_op {
     {OPK_C_READ_FAIL, NULL, 0, NULL, #stream_name},
 #define OP_C_STREAM_RESET(stream_name, aec)  \
     {OPK_C_STREAM_RESET, NULL, 0, NULL, #stream_name, (aec)},
+#define OP_S_ACCEPT_STREAM_WAIT(stream_name)  \
+    {OPK_S_ACCEPT_STREAM_WAIT, NULL, 0, NULL, #stream_name},
+#define OP_NEW_THREAD(num_threads, script) \
+    { OPK_NEW_THREAD, (script), (num_threads), NULL, NULL, 0 },
 
 static int check_rejected(struct helper *h, const struct script_op *op)
 {
@@ -228,8 +263,43 @@ static void helper_cleanup_streams(LHASH_OF(STREAM_INFO) **lh)
     *lh = NULL;
 }
 
+#if defined(OPENSSL_THREADS)
+static CRYPTO_THREAD_RETVAL run_script_child_thread(void *arg);
+
+static int join_threads(struct child_thread_args *threads, size_t num_threads)
+{
+    int ok = 1;
+    size_t i;
+    CRYPTO_THREAD_RETVAL rv;
+
+    for (i = 0; i < num_threads; ++i) {
+        if (threads[i].t != NULL) {
+            ossl_crypto_thread_native_join(threads[i].t, &rv);
+
+            if (!threads[i].testresult)
+                /* Do not log failure here, worker will do it. */
+                ok = 0;
+
+            ossl_crypto_thread_native_clean(threads[i].t);
+            threads[i].t = NULL;
+        }
+
+        ossl_crypto_mutex_free(&threads[i].m);
+    }
+
+    return ok;
+}
+#endif
+
 static void helper_cleanup(struct helper *h)
 {
+#if defined(OPENSSL_THREADS)
+    join_threads(h->threads, h->num_threads);
+    OPENSSL_free(h->threads);
+    h->threads = NULL;
+    h->num_threads = 0;
+#endif
+
     if (h->free_order == 0) {
         /* order 0: streams, then conn */
         helper_cleanup_streams(&h->c_streams);
@@ -367,6 +437,38 @@ err:
     return 0;
 }
 
+static int helper_local_init(struct helper_local *hl, struct helper *h,
+                             int thread_idx)
+{
+    hl->h           = h;
+    hl->c_streams   = NULL;
+    hl->thread_idx  = thread_idx;
+
+    if (!TEST_ptr(h))
+        return 0;
+
+    if (thread_idx < 0) {
+        hl->c_streams = h->c_streams;
+    } else {
+        if (!TEST_ptr(hl->c_streams = lh_STREAM_INFO_new(stream_info_hash,
+                                                         stream_info_cmp)))
+            return 0;
+    }
+
+    return 1;
+}
+
+static void helper_local_cleanup(struct helper_local *hl)
+{
+    if (hl->h == NULL)
+        return;
+
+    if (hl->thread_idx >= 0)
+        helper_cleanup_streams(&hl->c_streams);
+
+    hl->h = NULL;
+}
+
 static STREAM_INFO *get_stream_info(LHASH_OF(STREAM_INFO) *lh,
                                     const char *stream_name)
 {
@@ -393,10 +495,11 @@ static STREAM_INFO *get_stream_info(LHASH_OF(STREAM_INFO) *lh,
     return info;
 }
 
-static int helper_set_c_stream(struct helper *h, const char *stream_name,
-                               SSL *c_stream)
+static int helper_local_set_c_stream(struct helper_local *hl,
+                                     const char *stream_name,
+                                     SSL *c_stream)
 {
-    STREAM_INFO *info = get_stream_info(h->c_streams, stream_name);
+    STREAM_INFO *info = get_stream_info(hl->c_streams, stream_name);
 
     if (info == NULL)
         return 0;
@@ -406,14 +509,15 @@ static int helper_set_c_stream(struct helper *h, const char *stream_name,
     return 1;
 }
 
-static SSL *helper_get_c_stream(struct helper *h, const char *stream_name)
+static SSL *helper_local_get_c_stream(struct helper_local *hl,
+                                      const char *stream_name)
 {
     STREAM_INFO *info;
 
     if (!strcmp(stream_name, "DEFAULT"))
-        return h->c_conn;
+        return hl->h->c_conn;
 
-    info = get_stream_info(h->c_streams, stream_name);
+    info = get_stream_info(hl->c_streams, stream_name);
     if (info == NULL)
         return NULL;
 
@@ -459,25 +563,26 @@ static int is_want(SSL *s, int ret)
     return ec == SSL_ERROR_WANT_READ || ec == SSL_ERROR_WANT_WRITE;
 }
 
-static int run_script(const struct script_op *script, int free_order)
+static int run_script_worker(struct helper *h, const struct script_op *script,
+                             int thread_idx)
 {
-    size_t op_idx = 0;
     int testresult = 0;
-    int no_advance = 0, first = 1;
-    const struct script_op *op = NULL;
-    struct helper h;
     unsigned char *tmp_buf = NULL;
     int connect_started = 0;
-    OSSL_TIME op_start_time = ossl_time_zero(), op_deadline = ossl_time_zero();
     size_t offset = 0;
+    size_t op_idx = 0;
+    const struct script_op *op = NULL;
+    int no_advance = 0, first = 1, end_wait_warning = 0;
+    OSSL_TIME op_start_time = ossl_time_zero(), op_deadline = ossl_time_zero();
+    struct helper_local hl;
 
-    if (!TEST_true(helper_init(&h, free_order)))
+    if (!TEST_true(helper_local_init(&hl, h, thread_idx)))
         goto out;
 
 #define SPIN_AGAIN() { no_advance = 1; continue; }
 
     for (;;) {
-        SSL *c_tgt              = h.c_conn;
+        SSL *c_tgt              = h->c_conn;
         uint64_t s_stream_id    = UINT64_MAX;
 
         if (no_advance) {
@@ -493,31 +598,79 @@ static int run_script(const struct script_op *script, int free_order)
         }
 
         if (!TEST_int_le(ossl_time_compare(ossl_time_now(), op_deadline), 0)) {
-            TEST_error("op %zu timed out", op_idx + 1);
+            TEST_error("op %zu timed out on thread %d", op_idx + 1, thread_idx);
             goto out;
         }
 
         op = &script[op_idx];
 
         if (op->stream_name != NULL) {
-            c_tgt       = helper_get_c_stream(&h, op->stream_name);
-            s_stream_id = helper_get_s_stream(&h, op->stream_name);
+            c_tgt = helper_local_get_c_stream(&hl, op->stream_name);
+            if (thread_idx < 0)
+                s_stream_id = helper_get_s_stream(h, op->stream_name);
+            else
+                s_stream_id = UINT64_MAX;
+        }
+
+        if (thread_idx < 0) {
+            ossl_quic_tserver_tick(h->s);
+            if (connect_started)
+                SSL_tick(h->c_conn);
         }
 
-        ossl_quic_tserver_tick(h.s);
-        if (connect_started)
-            SSL_tick(h.c_conn);
+        if (thread_idx >= 0) {
+            /* Only allow certain opcodes on child threads. */
+            switch (op->op) {
+                case OPK_END:
+                case OPK_C_ACCEPT_STREAM_WAIT:
+                case OPK_C_NEW_STREAM:
+                case OPK_C_READ_EXPECT:
+                case OPK_C_EXPECT_FIN:
+                case OPK_C_WRITE:
+                case OPK_C_CONCLUDE:
+                case OPK_C_FREE_STREAM:
+                    break;
+
+                default:
+                    TEST_error("opcode %d not allowed on child thread", op->op);
+                    goto out;
+            }
+        }
 
         switch (op->op) {
         case OPK_END:
+            if (thread_idx < 0) {
+                int done;
+                size_t i;
+
+                for (i = 0; i < h->num_threads; ++i) {
+                    if (h->threads[i].m == NULL)
+                        continue;
+
+                    ossl_crypto_mutex_lock(h->threads[i].m);
+                    done = h->threads[i].done;
+                    ossl_crypto_mutex_unlock(h->threads[i].m);
+
+                    if (!done) {
+                        if (!end_wait_warning) {
+                            TEST_info("still waiting for other threads to finish (%zu)", i);
+                            end_wait_warning = 1;
+                        }
+
+                        SPIN_AGAIN();
+                    }
+                }
+            }
+
+            TEST_info("script finished on thread %d", thread_idx);
             testresult = 1;
             goto out;
 
         case OPK_CHECK:
             {
-                int ok = op->check_func(&h, op);
-                if (h.check_spin_again) {
-                    h.check_spin_again = 0;
+                int ok = op->check_func(h, op);
+                if (h->check_spin_again) {
+                    h->check_spin_again = 0;
                     SPIN_AGAIN();
                 }
 
@@ -539,7 +692,7 @@ static int run_script(const struct script_op *script, int free_order)
                 tmp_buf[0] = (unsigned char)alpn_len;
 
                 /* 0 is the success case for SSL_set_alpn_protos(). */
-                if (!TEST_false(SSL_set_alpn_protos(h.c_conn, tmp_buf,
+                if (!TEST_false(SSL_set_alpn_protos(h->c_conn, tmp_buf,
                                                     alpn_len + 1)))
                     goto out;
 
@@ -554,12 +707,12 @@ static int run_script(const struct script_op *script, int free_order)
 
                 connect_started = 1;
 
-                ret = SSL_connect(h.c_conn);
+                ret = SSL_connect(h->c_conn);
                 if (!TEST_true(ret == 1
-                               || (!h.blocking && is_want(h.c_conn, ret))))
+                               || (!h->blocking && is_want(h->c_conn, ret))))
                     goto out;
 
-                if (!h.blocking && ret != 1)
+                if (!h->blocking && ret != 1)
                     SPIN_AGAIN();
             }
             break;
@@ -585,7 +738,7 @@ static int run_script(const struct script_op *script, int free_order)
                 if (!TEST_uint64_t_ne(s_stream_id, UINT64_MAX))
                     goto out;
 
-                if (!TEST_true(ossl_quic_tserver_write(h.s, s_stream_id,
+                if (!TEST_true(ossl_quic_tserver_write(h->s, s_stream_id,
                                                        op->arg0, op->arg1,
                                                        &bytes_written))
                     || !TEST_size_t_eq(bytes_written, op->arg1))
@@ -605,7 +758,7 @@ static int run_script(const struct script_op *script, int free_order)
                 if (!TEST_uint64_t_ne(s_stream_id, UINT64_MAX))
                     goto out;
 
-                ossl_quic_tserver_conclude(h.s, s_stream_id);
+                ossl_quic_tserver_conclude(h->s, s_stream_id);
             }
             break;
 
@@ -660,7 +813,7 @@ static int run_script(const struct script_op *script, int free_order)
                     && !TEST_ptr(tmp_buf = OPENSSL_malloc(op->arg1)))
                     goto out;
 
-                if (!TEST_true(ossl_quic_tserver_read(h.s, s_stream_id,
+                if (!TEST_true(ossl_quic_tserver_read(h->s, s_stream_id,
                                                       tmp_buf + offset,
                                                       op->arg1 - offset,
                                                       &bytes_read)))
@@ -704,7 +857,7 @@ static int run_script(const struct script_op *script, int free_order)
                 if (!TEST_uint64_t_ne(s_stream_id, UINT64_MAX))
                     goto out;
 
-                if (!ossl_quic_tserver_has_read_ended(h.s, s_stream_id))
+                if (!ossl_quic_tserver_has_read_ended(h->s, s_stream_id))
                     SPIN_AGAIN();
             }
             break;
@@ -716,10 +869,10 @@ static int run_script(const struct script_op *script, int free_order)
                 if (!TEST_ptr_null(c_tgt))
                     goto out; /* don't overwrite existing stream with same name */
 
-                if (!TEST_ptr(c_stream = ossl_quic_detach_stream(h.c_conn)))
+                if (!TEST_ptr(c_stream = ossl_quic_detach_stream(h->c_conn)))
                     goto out;
 
-                if (!TEST_true(helper_set_c_stream(&h, op->stream_name, c_stream)))
+                if (!TEST_true(helper_local_set_c_stream(&hl, op->stream_name, c_stream)))
                     goto out;
             }
             break;
@@ -729,10 +882,10 @@ static int run_script(const struct script_op *script, int free_order)
                 if (!TEST_ptr(c_tgt))
                     goto out;
 
-                if (!TEST_true(ossl_quic_attach_stream(h.c_conn, c_tgt)))
+                if (!TEST_true(ossl_quic_attach_stream(h->c_conn, c_tgt)))
                     goto out;
 
-                if (!TEST_true(helper_set_c_stream(&h, op->stream_name, NULL)))
+                if (!TEST_true(helper_local_set_c_stream(&hl, op->stream_name, NULL)))
                     goto out;
             }
             break;
@@ -748,7 +901,7 @@ static int run_script(const struct script_op *script, int free_order)
                 if (op->arg1 != 0)
                     flags |= SSL_STREAM_FLAG_UNI;
 
-                if (!TEST_ptr(c_stream = SSL_new_stream(h.c_conn, flags)))
+                if (!TEST_ptr(c_stream = SSL_new_stream(h->c_conn, flags)))
                     goto out;
 
                 if (op->arg2 != UINT64_MAX
@@ -756,7 +909,7 @@ static int run_script(const struct script_op *script, int free_order)
                                          op->arg2))
                     goto out;
 
-                if (!TEST_true(helper_set_c_stream(&h, op->stream_name, c_stream)))
+                if (!TEST_true(helper_local_set_c_stream(&hl, op->stream_name, c_stream)))
                     goto out;
             }
             break;
@@ -768,7 +921,7 @@ static int run_script(const struct script_op *script, int free_order)
                 if (!TEST_uint64_t_eq(s_stream_id, UINT64_MAX))
                     goto out; /* don't overwrite existing stream with same name */
 
-                if (!TEST_true(ossl_quic_tserver_stream_new(h.s,
+                if (!TEST_true(ossl_quic_tserver_stream_new(h->s,
                                                             op->arg1 > 0,
                                                             &stream_id)))
                     goto out;
@@ -777,24 +930,40 @@ static int run_script(const struct script_op *script, int free_order)
                     && !TEST_uint64_t_eq(stream_id, op->arg2))
                     goto out;
 
-                if (!TEST_true(helper_set_s_stream(&h, op->stream_name,
+                if (!TEST_true(helper_set_s_stream(h, op->stream_name,
                                                    stream_id)))
                     goto out;
             }
             break;
 
-        case OPK_C_ACCEPT_STREAM:
+        case OPK_C_ACCEPT_STREAM_WAIT:
             {
                 SSL *c_stream;
 
                 if (!TEST_ptr_null(c_tgt))
                     goto out; /* don't overwrite existing stream with same name */
 
-                if ((c_stream = SSL_accept_stream(h.c_conn, 0)) == NULL)
+                if ((c_stream = SSL_accept_stream(h->c_conn, 0)) == NULL)
                     SPIN_AGAIN();
 
-                if (!TEST_true(helper_set_c_stream(&h, op->stream_name,
-                                                   c_stream)))
+                if (!TEST_true(helper_local_set_c_stream(&hl, op->stream_name,
+                                                          c_stream)))
+                    goto out;
+            }
+            break;
+
+        case OPK_S_ACCEPT_STREAM_WAIT:
+            {
+                uint64_t new_stream_id;
+
+                if (!TEST_uint64_t_eq(s_stream_id, UINT64_MAX))
+                    goto out;
+
+                new_stream_id = ossl_quic_tserver_pop_incoming_stream(h->s);
+                if (new_stream_id == UINT64_MAX)
+                    SPIN_AGAIN();
+
+                if (!TEST_true(helper_set_s_stream(h, op->stream_name, new_stream_id)))
                     goto out;
             }
             break;
@@ -803,7 +972,7 @@ static int run_script(const struct script_op *script, int free_order)
             {
                 SSL *c_stream;
 
-                if (!TEST_ptr_null(c_stream = SSL_accept_stream(h.c_conn, 0))) {
+                if (!TEST_ptr_null(c_stream = SSL_accept_stream(h->c_conn, 0))) {
                     SSL_free(c_stream);
                     goto out;
                 }
@@ -816,7 +985,7 @@ static int run_script(const struct script_op *script, int free_order)
                     || !TEST_true(!SSL_is_connection(c_tgt)))
                     goto out;
 
-                if (!TEST_true(helper_set_c_stream(&h, op->stream_name, NULL)))
+                if (!TEST_true(helper_local_set_c_stream(&hl, op->stream_name, NULL)))
                     goto out;
 
                 SSL_free(c_tgt);
@@ -886,10 +1055,10 @@ static int run_script(const struct script_op *script, int free_order)
                 int expect_remote = (op->arg1 & EXPECT_CONN_CLOSE_REMOTE) != 0;
                 uint64_t error_code = op->arg2;
 
-                if (!ossl_quic_tserver_is_term_any(h.s))
+                if (!ossl_quic_tserver_is_term_any(h->s))
                     SPIN_AGAIN();
 
-                if (!TEST_ptr(tc = ossl_quic_tserver_get_terminate_cause(h.s)))
+                if (!TEST_ptr(tc = ossl_quic_tserver_get_terminate_cause(h->s)))
                     goto out;
 
                 if (!TEST_uint64_t_eq(error_code, tc->error_code)
@@ -904,7 +1073,7 @@ static int run_script(const struct script_op *script, int free_order)
                 if (!TEST_uint64_t_eq(s_stream_id, UINT64_MAX))
                     goto out;
 
-                if (!TEST_true(helper_set_s_stream(&h, op->stream_name, op->arg2)))
+                if (!TEST_true(helper_set_s_stream(h, op->stream_name, op->arg2)))
                     goto out;
             }
             break;
@@ -928,7 +1097,7 @@ static int run_script(const struct script_op *script, int free_order)
                 if (!TEST_uint64_t_ne(s_stream_id, UINT64_MAX))
                     goto out;
 
-                if (!TEST_false(ossl_quic_tserver_write(h.s, s_stream_id,
+                if (!TEST_false(ossl_quic_tserver_write(h->s, s_stream_id,
                                                        (const unsigned char *)"apple", 5,
                                                        &bytes_written)))
                     goto out;
@@ -962,6 +1131,44 @@ static int run_script(const struct script_op *script, int free_order)
             }
             break;
 
+        case OPK_NEW_THREAD:
+            {
+#if !defined(OPENSSL_THREADS)
+                TEST_error("threading not supported");
+                goto out;
+#else
+                size_t i;
+
+                if (!TEST_ptr_null(h->threads)) {
+                    TEST_error("max one NEW_THREAD operation per script");
+                    goto out;
+                }
+
+                h->threads = OPENSSL_zalloc(op->arg1 * sizeof(struct child_thread_args));
+                if (!TEST_ptr(h->threads))
+                    goto out;
+
+                h->num_threads = op->arg1;
+
+                for (i = 0; i < op->arg1; ++i) {
+                    h->threads[i].h            = h;
+                    h->threads[i].script       = op->arg0;
+                    h->threads[i].thread_idx   = i;
+
+                    h->threads[i].m = ossl_crypto_mutex_new();
+                    if (!TEST_ptr(h->threads[i].m))
+                        goto out;
+
+                    h->threads[i].t
+                        = ossl_crypto_thread_native_start(run_script_child_thread,
+                                                          &h->threads[i], 1);
+                    if (!TEST_ptr(h->threads[i].t))
+                        goto out;
+                }
+#endif
+            }
+            break;
+
         default:
             TEST_error("unknown op");
             goto out;
@@ -970,13 +1177,51 @@ static int run_script(const struct script_op *script, int free_order)
 
 out:
     if (!testresult)
-        TEST_error("failed at script op %zu\n", op_idx + 1);
+        TEST_error("failed at script op %zu, thread %d\n",
+                   op_idx + 1, thread_idx);
 
     OPENSSL_free(tmp_buf);
+    helper_local_cleanup(&hl);
+    return testresult;
+}
+
+static int run_script(const struct script_op *script, int free_order)
+{
+    int testresult = 0;
+    struct helper h;
+
+    if (!TEST_true(helper_init(&h, free_order)))
+        goto out;
+
+    if (!TEST_true(run_script_worker(&h, script, -1)))
+        goto out;
+
+    if (!TEST_true(join_threads(h.threads, h.num_threads)))
+        goto out;
+
+    testresult = 1;
+out:
     helper_cleanup(&h);
     return testresult;
 }
 
+#if defined(OPENSSL_THREADS)
+static CRYPTO_THREAD_RETVAL run_script_child_thread(void *arg)
+{
+    int testresult;
+    struct child_thread_args *args = arg;
+
+    testresult = run_script_worker(args->h, args->script,
+                                   args->thread_idx);
+
+    ossl_crypto_mutex_lock(args->m);
+    args->testresult    = testresult;
+    args->done          = 1;
+    ossl_crypto_mutex_unlock(args->m);
+    return 1;
+}
+#endif
+
 /* 1. Simple single-stream test */
 static const struct script_op script_1[] = {
     OP_C_SET_ALPN           ("ossltest")
@@ -1029,7 +1274,7 @@ static const struct script_op script_2[] = {
     OP_S_WRITE              (d, "frog", 4)
     OP_S_CONCLUDE           (d)
 
-    OP_C_ACCEPT_STREAM      (d)
+    OP_C_ACCEPT_STREAM_WAIT (d)
     OP_C_ACCEPT_STREAM_NONE ()
     OP_C_READ_EXPECT        (d, "frog", 4)
     OP_C_EXPECT_FIN         (d)
@@ -1038,7 +1283,7 @@ static const struct script_op script_2[] = {
     OP_S_WRITE              (e, "mixture", 7)
     OP_S_CONCLUDE           (e)
 
-    OP_C_ACCEPT_STREAM      (e)
+    OP_C_ACCEPT_STREAM_WAIT (e)
     OP_C_READ_EXPECT        (e, "mixture", 7)
     OP_C_EXPECT_FIN         (e)
     OP_C_WRITE              (e, "ramble", 6)
@@ -1050,7 +1295,7 @@ static const struct script_op script_2[] = {
     OP_S_WRITE              (f, "yonder", 6)
     OP_S_CONCLUDE           (f)
 
-    OP_C_ACCEPT_STREAM      (f)
+    OP_C_ACCEPT_STREAM_WAIT (f)
     OP_C_ACCEPT_STREAM_NONE ()
     OP_C_READ_EXPECT        (f, "yonder", 6)
     OP_C_EXPECT_FIN         (f)
@@ -1122,7 +1367,7 @@ static const struct script_op script_4[] = {
 
     OP_C_READ_FAIL          (DEFAULT)
 
-    OP_C_ACCEPT_STREAM      (a)
+    OP_C_ACCEPT_STREAM_WAIT (a)
     OP_C_READ_EXPECT        (a, "apple", 5)
 
     OP_C_ATTACH             (a)
@@ -1159,7 +1404,7 @@ static const struct script_op script_6[] = {
     OP_S_NEW_STREAM_BIDI    (a, S_BIDI_ID(0))
     OP_S_WRITE              (a, "apple", 5)
 
-    OP_C_ACCEPT_STREAM      (a)
+    OP_C_ACCEPT_STREAM_WAIT (a)
     OP_C_FREE_STREAM        (a)
     OP_C_ACCEPT_STREAM_NONE ()