Skip to content

Commit

Permalink
Merge pull request #21434 from JuliaLang/jb/fix21369
Browse files Browse the repository at this point in the history
fix #21369, exception state overwritten by caught internal errors
  • Loading branch information
JeffBezanson committed Apr 20, 2017
2 parents a58e8f0 + 4f256ee commit 762c6db
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 14 deletions.
22 changes: 9 additions & 13 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2154,24 +2154,20 @@ static jl_value_t *static_eval(jl_value_t *ex, jl_codectx_t *ctx, int sparams=tr
if (!allow_alloc)
return NULL;
jl_value_t **v;
JL_GC_PUSHARGS(v, n);
JL_GC_PUSHARGS(v, n+1);
v[0] = f;
for (i = 0; i < n; i++) {
v[i] = static_eval(jl_exprarg(e, i+1), ctx, sparams, allow_alloc);
if (v[i] == NULL) {
v[i+1] = static_eval(jl_exprarg(e, i+1), ctx, sparams, allow_alloc);
if (v[i+1] == NULL) {
JL_GC_POP();
return NULL;
}
}
jl_value_t *result;
JL_TRY {
if (f == jl_builtin_tuple)
result = jl_f_tuple(NULL, v, n);
else
result = jl_f_apply_type(NULL, v, n);
}
JL_CATCH {
result = NULL;
}
size_t last_age = jl_get_ptls_states()->world_age;
// here we know we're calling specific builtin functions that work in world 1.
jl_get_ptls_states()->world_age = 1;
jl_value_t *result = jl_apply_with_saved_exception_state(v, n+1, 1);
jl_get_ptls_states()->world_age = last_age;
JL_GC_POP();
return result;
}
Expand Down
12 changes: 12 additions & 0 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,20 @@ static void jl_gc_run_finalizers_in_list(jl_ptls_t ptls, arraylist_t *list)
jl_value_t **items = (jl_value_t**)list->items;
jl_gc_push_arraylist(ptls, list);
JL_UNLOCK_NOGC(&finalizers_lock);
// from jl_apply_with_saved_exception_state; to hoist state saving out of the loop
jl_value_t *exc = ptls->exception_in_transit;
jl_array_t *bt = NULL;
JL_GC_PUSH2(&exc, &bt);
if (ptls->bt_size > 0)
bt = (jl_array_t*)jl_get_backtrace();
for (size_t i = 2;i < len;i += 2)
run_finalizer(ptls, items[i], items[i + 1]);
ptls->exception_in_transit = exc;
if (bt != NULL) {
ptls->bt_size = jl_array_len(bt);
memcpy(ptls->bt_data, bt->data, ptls->bt_size * sizeof(void*));
}
JL_GC_POP();
JL_GC_POP();
}

Expand Down
2 changes: 1 addition & 1 deletion src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int forc
}
#endif
jl_get_ptls_states()->world_age = jl_typeinf_world;
jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply(fargs, 3);
jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply_with_saved_exception_state(fargs, 3, 0);
jl_get_ptls_states()->world_age = last_age;
assert((li->def || li->inInference == 0) && "inference failed on a toplevel expr");
if (jl_is_svec(linfo_src_rettype) && jl_svec_len(linfo_src_rettype) == 3 &&
Expand Down
2 changes: 2 additions & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,8 @@ size_t rec_backtrace_ctx(uintptr_t *data, size_t maxsize, bt_context_t *ctx);
#ifdef LIBOSXUNWIND
size_t rec_backtrace_ctx_dwarf(uintptr_t *data, size_t maxsize, bt_context_t *ctx);
#endif
JL_DLLEXPORT jl_value_t *jl_get_backtrace(void);
JL_DLLEXPORT jl_value_t *jl_apply_with_saved_exception_state(jl_value_t **args, uint32_t nargs, int catch_exceptions);
void jl_critical_error(int sig, bt_context_t *context, uintptr_t *bt_data, size_t *bt_size);
JL_DLLEXPORT void jl_raise_debugger(void);
int jl_getFunctionInfo(jl_frame_t **frames, uintptr_t pointer, int skipC, int noInline);
Expand Down
29 changes: 29 additions & 0 deletions src/rtutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,35 @@ JL_DLLEXPORT void jl_pop_handler(int n)
jl_eh_restore_state(eh);
}

JL_DLLEXPORT jl_value_t *jl_apply_with_saved_exception_state(jl_value_t **args, uint32_t nargs, int catch_exceptions)
{
jl_ptls_t ptls = jl_get_ptls_states();
jl_value_t *exc = ptls->exception_in_transit;
jl_array_t *bt = NULL;
JL_GC_PUSH2(&exc, &bt);
if (ptls->bt_size > 0)
bt = (jl_array_t*)jl_get_backtrace();
jl_value_t *v;
if (catch_exceptions) {
JL_TRY {
v = jl_apply(args, nargs);
}
JL_CATCH {
v = NULL;
}
}
else {
v = jl_apply(args, nargs);
}
ptls->exception_in_transit = exc;
if (bt != NULL) {
ptls->bt_size = jl_array_len(bt);
memcpy(ptls->bt_data, bt->data, ptls->bt_size * sizeof(void*));
}
JL_GC_POP();
return v;
}

// misc -----------------------------------------------------------------------

// perform f(args...) on stack
Expand Down
28 changes: 28 additions & 0 deletions test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -748,3 +748,31 @@ end
# issue #21410
f21410(::V, ::Pair{V,E}) where {V, E} = E
@test code_typed(f21410, Tuple{Ref, Pair{Ref{T},Ref{T}} where T<:Number})[1].second == Type{Ref{T}} where T<:Number

# issue #21369
function inf_error_21369(arg)
if arg
# invalid instantiation, causing throw during inference
Complex{String}
end
end
function break_21369()
try
error("uhoh")
catch
eval(:(inf_error_21369(false)))
bt = catch_backtrace()
i = 1
local fr
while true
fr = Base.StackTraces.lookup(bt[i])[end]
if !fr.from_c
break
end
i += 1
end
@test fr.func === :break_21369
rethrow()
end
end
@test_throws ErrorException break_21369() # not TypeError

2 comments on commit 762c6db

@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)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

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

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

Please sign in to comment.