Skip to content

Deadlock when Julia is initialized from constructor function. #60513

@tz-lom

Description

@tz-lom

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:

  1. dlopen is loading my Julia compiled library and set a thread lock
  2. During _dl_init phase it will call init_julia function which will call jl_init_with_image_handle
  3. Because I request extra thread, ijl_init_ will start extra thread
  4. All thread initialization is synchronized in _finish_jl_init_ with wait on a barrier
  5. New thread will run jl_concurrent_gc_threadfun which calls to jl_init_threadtls
  6. jl_init_threadtls want to call to libunwind unw_ensure_tls function before hitting the wait barrier few lines bellow
    jl_dlsym(jl_RTLD_DEFAULT_handle, "unw_ensure_tls", (void**)&jl_unw_ensure_tls, 0, 1);

    Because it does dynamic symbol lookup - it calls to dlsym which hits a thread lock from the step 1
  7. We are now in deadlock.

Possible solutions:

  • Perform unw_ensure_tls after wait barrier (what will happen if thread initialization code would break?)
  • Do dynamic linking to unw_ensure_tls instead of runtime linking (libjulia-internal anyway is linked to libunwind already, no need for dynamic name resolution)
  • Resolve unw_ensure_tls in ijl_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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions