From 45b7e7ab2b6ec90dfa4b4f156c5c5d77ebe28b8b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 28 Jan 2023 23:06:21 -0500 Subject: [PATCH] avoid hang when only threads are starting IO (#48433) When not in threaded region, only thread 0 will manage IO events, but it may have gone to sleep if there were no IO objects active for it to watch earlier. Fix #48430 --- src/partr.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/partr.c b/src/partr.c index 4faff409c711a..b51f5eee8089f 100644 --- a/src/partr.c +++ b/src/partr.c @@ -229,7 +229,7 @@ JL_DLLEXPORT void jl_wakeup_thread(int16_t tid) JL_NOTSAFEPOINT } else { // something added to the sticky-queue: notify that thread - if (wake_thread(tid)) { + if (wake_thread(tid) && uvlock != ct) { // check if we need to notify uv_run too jl_fence(); jl_ptls_t other = jl_atomic_load_relaxed(&jl_all_tls_states)[tid]; @@ -237,7 +237,7 @@ JL_DLLEXPORT void jl_wakeup_thread(int16_t tid) JL_NOTSAFEPOINT // now that we have changed the thread to not-sleeping, ensure that // either it has not yet acquired the libuv lock, or that it will // observe the change of state to not_sleeping - if (uvlock != ct && jl_atomic_load_relaxed(&jl_uv_mutex.owner) == tid_task) + if (jl_atomic_load_relaxed(&jl_uv_mutex.owner) == tid_task) wake_libuv(); } } @@ -386,7 +386,16 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, } else if (ptls->tid == 0) { uvlock = 1; - JL_UV_LOCK(); // jl_mutex_lock(&jl_uv_mutex); + JL_UV_LOCK(); + } + else { + // Since we might have started some IO work, we might need + // to ensure tid = 0 will go watch that new event source. + // If trylock would have succeeded, that may have been our + // responsibility, so need to make sure thread 0 will take care + // of us. + if (jl_atomic_load_relaxed(&jl_uv_mutex.owner) == NULL) // aka trylock + jl_wakeup_thread(0); } if (uvlock) { int enter_eventloop = may_sleep(ptls);