Skip to content

Commit

Permalink
Try to fix deadlock in code loading (#28416)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Keno authored Aug 3, 2018
1 parent b70d214 commit 0e32871
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 4 deletions.
4 changes: 3 additions & 1 deletion base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
6 changes: 3 additions & 3 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
37 changes: 37 additions & 0 deletions test/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

1 comment on commit 0e32871

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

Please sign in to comment.