-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Open
Description
If I use following initializer in Julia compiled library:
void __attribute__((constructor)) init_julia()
{
jl_options.nthreads = 1;
static int16_t threads_per_pool[1] = {1};
jl_options.nthreads_per_pool = threads_per_pool;
jl_options.nthreadpools = 1;
jl_options.nmarkthreads = 1;
jl_options.nsweepthreads = 1; // this will request a sweep thread
jl_init_with_image_handle((void *)RTLD_DEFAULT);
}And then I will load this library in runtime it will cause a deadlock:
Here is what will happen:
dlopenis loading my Julia compiled library and set a thread lock- During
_dl_initphase it will callinit_juliafunction which will calljl_init_with_image_handle - Because I request extra thread,
ijl_init_will start extra thread - All thread initialization is synchronized in
_finish_jl_init_with wait on a barrier - New thread will run
jl_concurrent_gc_threadfunwhich calls tojl_init_threadtls jl_init_threadtlswant to call to libunwindunw_ensure_tlsfunction before hitting the wait barrier few lines bellow
Line 398 in 812f3be
jl_dlsym(jl_RTLD_DEFAULT_handle, "unw_ensure_tls", (void**)&jl_unw_ensure_tls, 0, 1);
Because it does dynamic symbol lookup - it calls todlsymwhich hits a thread lock from the step 1- We are now in deadlock.
Possible solutions:
- Perform
unw_ensure_tlsafter wait barrier (what will happen if thread initialization code would break?) - Do dynamic linking to
unw_ensure_tlsinstead of runtime linking (libjulia-internal anyway is linked to libunwind already, no need for dynamic name resolution) - Resolve
unw_ensure_tlsinijl_init_and store it for later use in all threads (so no dynamic name resolution will be performed in separate thread an libdl will not cause deadlock)
Metadata
Metadata
Assignees
Labels
No labels