-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make sleep(n) and Timer creation more MT-safe #32174
Conversation
|
src/jl_uv.c
Outdated
return err; | ||
} | ||
|
||
jl_uv_associate_julia_struct((uv_handle_t *)handle, (jl_value_t *)handle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one of these things is not like the other—you can't cast to both libuv and julia
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I'm getting slightly confused by what's what, since in the following two locations it seems that we're already passing objects which (to my uneducated eyes) seem to end up with casts that are essentially the same as what you pointed out at:
Line 90 in 4b0c8e7
err = ccall(:uv_timer_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}), eventloop(), this) |
Lines 102 to 103 in 4b0c8e7
ccall(:uv_timer_start, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, UInt64, UInt64), | |
this, uv_jl_timercb::Ptr{Cvoid}, |
Those two libuv calls don't expect a jl_value_t*
, even though that's what we're doing there, right? I assume it works because this.handle
is the first field in the Timer
struct so the pointers are the same anyway?
src/jl_uv.c
Outdated
int err = uv_timer_init(loop, handle); | ||
if (err) { | ||
// TODO: this codepath is currently not tested | ||
free(handle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing JL_UV_UNLOCK on this codepath, also probably better to keep the free
call in Julia
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully my latest commit addresses both of these properly 😄
src/jl_uv.c
Outdated
{ | ||
JL_UV_LOCK(); | ||
int err = uv_timer_init(loop, uvtimer); | ||
if (err) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this actually can't fail, so we can just delete the error checking code (or make it an abort)
|
||
jl_uv_associate_julia_struct((uv_handle_t*)uvtimer, jltimer); | ||
uv_update_time(loop); | ||
err = uv_timer_start(uvtimer, cb, timeout, repeat); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similarly, this can't actually fail either, we can just abort
if it returns non-zero
I believe I encountered one of the hanging conditions mentioned at the top of this PR, and wanted to note for others that |
This returns some of the locking removed by 93e3d28 (which @JeffBezanson said was removed because it was probably incorrect), but this time the calls to
uv_update_time
anduv_timer_start
are done within a single lock/unlock of the global libuv lock (instead of two separate lock/unlock pairs).This still hangs every so often on my system with
JULIA_NUM_THREADS=8
when running a slightly longer version of the test laid out in #32152, which I'd like to have this PR fix once I figure out the root cause. I also think this PR should have at least one test to ensure highly-contended calls tosleep
orTimer
don't cause segfaults or hangs; I'll add a simple test to this PR soon to get something on the table.(Eventually) fixes #32152