From b6f1be5c51f4a5cbf94ad2c0f7a49ceaefd36dff Mon Sep 17 00:00:00 2001 From: Julian Samaroo Date: Mon, 3 Jun 2019 21:46:08 -0500 Subject: [PATCH] Make sleep(n) and Timer creation more MT-safe (#32174) fixes #32152 --- base/asyncevent.jl | 18 ++++-------------- src/jl_uv.c | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/base/asyncevent.jl b/base/asyncevent.jl index ac2a181cc91c0..2299993bd2ea0 100644 --- a/base/asyncevent.jl +++ b/base/asyncevent.jl @@ -87,21 +87,11 @@ mutable struct Timer interval ≥ 0 || throw(ArgumentError("timer cannot have negative repeat interval of $interval seconds")) this = new(Libc.malloc(_sizeof_uv_timer), ThreadSynchronizer(), true) - err = ccall(:uv_timer_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), eventloop(), this) - if err != 0 - #TODO: this codepath is currently not tested - Libc.free(this.handle) - this.handle = C_NULL - throw(_UVError("uv_timer_init", err)) - end - - associate_julia_struct(this.handle, this) - finalizer(uvfinalize, this) - - ccall(:uv_update_time, Cvoid, (Ptr{Cvoid},), eventloop()) - ccall(:uv_timer_start, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, UInt64, UInt64), - this, uv_jl_timercb::Ptr{Cvoid}, + ccall(:jl_uv_update_timer_start, Cvoid, + (Ptr{Cvoid}, Any, Ptr{Cvoid}, Ptr{Cvoid}, UInt64, UInt64), + eventloop(), this, this.handle, uv_jl_timercb::Ptr{Cvoid}, UInt64(round(timeout * 1000)) + 1, UInt64(round(interval * 1000))) + finalizer(uvfinalize, this) return this end end diff --git a/src/jl_uv.c b/src/jl_uv.c index f92ce0bcb5a1e..fc4eb147cc755 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -1085,6 +1085,23 @@ JL_DLLEXPORT int jl_queue_work(work_cb_t work_func, void *work_args, void *work_ return 0; } +JL_DLLEXPORT void jl_uv_update_timer_start(uv_loop_t* loop, jl_value_t* jltimer, + uv_timer_t* uvtimer, uv_timer_cb cb, + uint64_t timeout, uint64_t repeat) +{ + JL_UV_LOCK(); + int err = uv_timer_init(loop, uvtimer); + if (err) + abort(); + + jl_uv_associate_julia_struct((uv_handle_t*)uvtimer, jltimer); + uv_update_time(loop); + err = uv_timer_start(uvtimer, cb, timeout, repeat); + if (err) + abort(); + JL_UV_UNLOCK(); +} + JL_DLLEXPORT void jl_uv_stop(uv_loop_t* loop) { JL_UV_LOCK();