From 0e32871bfcee426fc4bf8c5d70af3f472b069868 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 2 Aug 2018 23:10:44 -0400 Subject: [PATCH] Try to fix deadlock in code loading (#28416) If a precompiled package's init function tries to itself require that package (e.g. by importing a symbol from a submodule of that package), we would run into a deadlock. Fix that by delaying the running of initializers until after we've had a chance to register any root module. Fixes #26028 --- base/loading.jl | 4 +++- src/dump.c | 6 +++--- test/precompile.jl | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index ae913e58a73cb..10f1f555033f2 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -611,7 +611,8 @@ end # or an Exception that describes why it couldn't be loaded # and it reconnects the Base.Docs.META function _include_from_serialized(path::String, depmods::Vector{Any}) - restored = ccall(:jl_restore_incremental, Any, (Cstring, Any), path, depmods) + sv = ccall(:jl_restore_incremental, Any, (Cstring, Any), path, depmods) + restored = sv[1] if !isa(restored, Exception) for M in restored::Vector{Any} M = M::Module @@ -623,6 +624,7 @@ function _include_from_serialized(path::String, depmods::Vector{Any}) end end end + isassigned(sv, 2) && ccall(:jl_init_restored_modules, Cvoid, (Any,), sv[2]) return restored end diff --git a/src/dump.c b/src/dump.c index bd82b0237bfad..d1eddab89eb0f 100644 --- a/src/dump.c +++ b/src/dump.c @@ -2402,7 +2402,7 @@ static jl_array_t *jl_finalize_deserializer(jl_serializer_state *s, arraylist_t return init_order; } -static void jl_init_restored_modules(jl_array_t *init_order) +JL_DLLEXPORT void jl_init_restored_modules(jl_array_t *init_order) { if (!init_order) return; @@ -3118,10 +3118,10 @@ static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array) arraylist_free(tracee_list); free(tracee_list); } - jl_init_restored_modules(init_order); + jl_value_t *ret = (jl_value_t*)jl_svec(2, restored, init_order); JL_GC_POP(); - return (jl_value_t*)restored; + return (jl_value_t*)ret; } JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz, jl_array_t *mod_array) diff --git a/test/precompile.jl b/test/precompile.jl index b88651e9afd38..fa44c465960aa 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -700,4 +700,41 @@ let end end +let + load_path = mktempdir() + load_cache_path = mktempdir() + try + write(joinpath(load_path, "Foo26028.jl"), + """ + module Foo26028 + + module Bar26028 + x = 0 + end + + function __init__() + include(joinpath(@__DIR__, "Baz26028.jl")) + end + + end + """) + write(joinpath(load_path, "Baz26028.jl"), + """ + module Baz26028 + import Foo26028.Bar26028.x + end + """) + + pushfirst!(LOAD_PATH, load_path) + pushfirst!(DEPOT_PATH, load_cache_path) + + Base.compilecache(Base.PkgId("Foo26028")) + @test_nowarn @eval using Foo26028 + finally + rm(load_path, recursive=true) + rm(load_cache_path, recursive=true) + end +end + + end # !withenv