diff --git a/base/Base.jl b/base/Base.jl index 22e8b48288efc..20e729256664f 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -447,6 +447,10 @@ for m in methods(include) delete_method(m) end +# This method is here only to be overwritten during the test suite to test +# various sysimg related invalidation scenarios. +a_method_to_overwrite_in_test() = inferencebarrier(1) + # These functions are duplicated in client.jl/include(::String) for # nicer stacktraces. Modifications here have to be backported there include(mod::Module, _path::AbstractString) = _include(identity, mod, _path) diff --git a/src/gf.c b/src/gf.c index 481297765ff6c..af9061737b319 100644 --- a/src/gf.c +++ b/src/gf.c @@ -280,6 +280,13 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t *mi, size_t world, int force) if (jl_typeinf_func == NULL) return NULL; jl_task_t *ct = jl_current_task; + if (ct->reentrant_inference == (uint16_t)-1) { + // TODO: We should avoid attempting to re-inter inference here at all + // and turn on this warning, but that requires further refactoring + // of the precompile code, so for now just catch that case here. + //jl_printf(JL_STDERR, "ERROR: Attempted to enter inference while writing out image."); + return NULL; + } if (ct->reentrant_inference > 2) return NULL; diff --git a/src/staticdata.c b/src/staticdata.c index 7439386483f9b..929c44273a6ef 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -2614,7 +2614,12 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli } else { checksumpos_ff = checksumpos; } - jl_gc_enable_finalizers(ct, 0); // make sure we don't run any Julia code concurrently after this point + { + // make sure we don't run any Julia code concurrently after this point + jl_gc_enable_finalizers(ct, 0); + assert(ct->reentrant_inference == 0); + ct->reentrant_inference = (uint16_t)-1; + } jl_prepare_serialization_data(mod_array, newly_inferred, jl_worklist_key(worklist), &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges); // Generate _native_data` @@ -2638,7 +2643,9 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli jl_save_system_image_to_stream(ff, worklist, extext_methods, new_specializations, method_roots_list, ext_targets, edges); native_functions = NULL; if (worklist) { - jl_gc_enable_finalizers(ct, 1); // make sure we don't run any Julia code concurrently before this point + // Re-enable running julia code for postoutput hooks, atexit, etc. + jl_gc_enable_finalizers(ct, 1); + ct->reentrant_inference = 0; jl_precompile_toplevel_module = NULL; } diff --git a/test/precompile.jl b/test/precompile.jl index 8aa09efe3f417..8f8c8202832ee 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -1691,6 +1691,23 @@ precompile_test_harness("DynamicExpressions") do load_path end end +precompile_test_harness("BadInvalidations") do load_path + write(joinpath(load_path, "BadInvalidations.jl"), + """ + module BadInvalidations + Base.Experimental.@compiler_options compile=min optimize=1 + getval() = Base.a_method_to_overwrite_in_test() + getval() + end # module BadInvalidations + """) + Base.compilecache(Base.PkgId("BadInvalidations")) + (@eval Base a_method_to_overwrite_in_test() = inferencebarrier(2)) + (@eval (using BadInvalidations)) + Base.invokelatest() do + @test BadInvalidations.getval() === 2 + end +end + empty!(Base.DEPOT_PATH) append!(Base.DEPOT_PATH, original_depot_path) empty!(Base.LOAD_PATH)