Skip to content

Commit

Permalink
fix #21369, exception state overwritten by caught internal errors
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Apr 18, 2017
1 parent b0c7084 commit ba8bf6a
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 15 deletions.
18 changes: 5 additions & 13 deletions src/codegen.cpp
Expand Up @@ -2145,24 +2145,16 @@ 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;
}
jl_value_t *result = jl_apply_with_saved_exception_state(v, n+1, 1);
JL_GC_POP();
return result;
}
Expand Down
2 changes: 1 addition & 1 deletion src/gc.c
Expand Up @@ -108,7 +108,7 @@ static void run_finalizer(jl_ptls_t ptls, jl_value_t *o, jl_value_t *ff)
JL_TRY {
size_t last_age = jl_get_ptls_states()->world_age;
jl_get_ptls_states()->world_age = jl_world_counter;
jl_apply(args, 2);
jl_apply_with_saved_exception_state(args, 2, 0);
jl_get_ptls_states()->world_age = last_age;
}
JL_CATCH {
Expand Down
2 changes: 1 addition & 1 deletion src/gf.c
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
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
30 changes: 30 additions & 0 deletions src/rtutils.c
Expand Up @@ -236,6 +236,36 @@ 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 = NULL;
jl_array_t *bt = NULL;
JL_GC_PUSH2(&exc, &bt);
exc = ptls->exception_in_transit;
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
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

0 comments on commit ba8bf6a

Please sign in to comment.