From 649c81bd0a4703b7c71cdcdb8b4329b6d110134f Mon Sep 17 00:00:00 2001 From: William Yang Date: Fri, 8 Sep 2023 22:55:39 +0200 Subject: [PATCH] fix(conn): deadlock when async_connect with 0-RTT msquic does conn callback with StreamsAvailable event in the same code path of set conn param session ticket. This causes deadlock when callback handler wait for quicer async_connect to release the lock of c_ctx when it is called with an opened handle. solution is to either do set session ticket in open_connection Or set session ticket in async_connect without an opened handle callstack: at /home/ubuntu/repo/quic/msquic/src/core/stream_set.c:343 --- c_src/quicer_connection.c | 44 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/c_src/quicer_connection.c b/c_src/quicer_connection.c index 06713355..ea0c2b97 100644 --- a/c_src/quicer_connection.c +++ b/c_src/quicer_connection.c @@ -507,6 +507,7 @@ open_connectionX(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) ERL_NIF_TERM res = ERROR_TUPLE_2(ATOM_ERROR_INTERNAL_ERROR); QuicerRegistrationCTX *r_ctx = NULL; HQUIC registration = NULL; + ERL_NIF_TERM options = argv[1]; if (argc == 0) { @@ -516,7 +517,6 @@ open_connectionX(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) else { assert(argc == 1); - ERL_NIF_TERM options = argv[1]; if (!parse_registration(env, options, &r_ctx)) { return ERROR_TUPLE_2(ATOM_QUIC_REGISTRATION); @@ -562,6 +562,12 @@ open_connectionX(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) goto exit; } + if (!IS_SAME_TERM(ATOM_OK, + (res = parse_conn_resume_ticket(env, options, c_ctx)))) + { + goto exit; + } + eHandle = enif_make_resource(env, c_ctx); return SUCCESS(eHandle); @@ -666,12 +672,10 @@ async_connect3(ErlNifEnv *env, } } - if (is_reuse_handle) - { - enif_mutex_lock(c_ctx->lock); - } - + { + enif_mutex_lock(c_ctx->lock); + } assert(c_ctx->owner); // allocate config_resource for client connection @@ -723,6 +727,12 @@ async_connect3(ErlNifEnv *env, res = ERROR_TUPLE_2(ATOM_CONN_OPEN_ERROR); goto Error; } + + if (!IS_SAME_TERM( + ATOM_OK, (res = parse_conn_resume_ticket(env, eoptions, c_ctx)))) + { + goto Error; + } } assert(c_ctx->is_closed); @@ -737,12 +747,6 @@ async_connect3(ErlNifEnv *env, goto Error; } - if (!IS_SAME_TERM(ATOM_OK, - (res = parse_conn_resume_ticket(env, eoptions, c_ctx)))) - { - goto Error; - } - if (!IS_SAME_TERM( ATOM_OK, (res = parse_conn_disable_1rtt_encryption(env, eoptions, c_ctx)))) @@ -789,10 +793,10 @@ async_connect3(ErlNifEnv *env, enif_monitor_process(NULL, c_ctx, &c_ctx->owner->Pid, &c_ctx->owner_mon); eHandle = enif_make_resource(env, c_ctx); - if(is_reuse_handle) - { - enif_mutex_unlock(c_ctx->lock); - } + if (is_reuse_handle) + { + enif_mutex_unlock(c_ctx->lock); + } return SUCCESS(eHandle); Error: @@ -842,10 +846,10 @@ async_connect3(ErlNifEnv *env, // Error exit, it must be closed or Handle is NULL assert(c_ctx->is_closed || NULL == c_ctx->Connection); - if(is_reuse_handle) - { - enif_mutex_unlock(c_ctx->lock); - } + if (is_reuse_handle) + { + enif_mutex_unlock(c_ctx->lock); + } return res; }