1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

solve "duplicate :raise event" [Bug #15877]

Without this patch, "raise" event invoked twice when raise an
exception in "load"ed script.
This patch by  danielwaterworth (Daniel Waterworth).
[Bug #15877]
This commit is contained in:
Koichi Sasada 2019-08-08 17:53:36 +09:00
parent 20cb8e8aea
commit b004d3e830
4 changed files with 24 additions and 36 deletions

View file

@ -277,9 +277,7 @@ NORETURN(void rb_print_undef(VALUE, ID, rb_method_visibility_t));
NORETURN(void rb_print_undef_str(VALUE, VALUE)); NORETURN(void rb_print_undef_str(VALUE, VALUE));
NORETURN(void rb_print_inaccessible(VALUE, ID, rb_method_visibility_t)); NORETURN(void rb_print_inaccessible(VALUE, ID, rb_method_visibility_t));
NORETURN(void rb_vm_localjump_error(const char *,VALUE, int)); NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
#if 0
NORETURN(void rb_vm_jump_tag_but_local_jump(int)); NORETURN(void rb_vm_jump_tag_but_local_jump(int));
#endif
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val); VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val);
rb_cref_t *rb_vm_cref(void); rb_cref_t *rb_vm_cref(void);

43
load.c
View file

@ -568,7 +568,7 @@ rb_provide(const char *feature)
NORETURN(static void load_failed(VALUE)); NORETURN(static void load_failed(VALUE));
static int static inline void
rb_load_internal0(rb_execution_context_t *ec, VALUE fname, int wrap) rb_load_internal0(rb_execution_context_t *ec, VALUE fname, int wrap)
{ {
enum ruby_tag_type state; enum ruby_tag_type state;
@ -621,59 +621,40 @@ rb_load_internal0(rb_execution_context_t *ec, VALUE fname, int wrap)
th->top_wrapper = wrapper; th->top_wrapper = wrapper;
if (state) { if (state) {
/* usually state == TAG_RAISE only, except for rb_vm_jump_tag_but_local_jump(state);
* rb_iseq_load_iseq case */
VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef);
if (NIL_P(exc)) return state;
th->ec->errinfo = exc;
return TAG_RAISE;
} }
if (!NIL_P(th->ec->errinfo)) { if (!NIL_P(th->ec->errinfo)) {
/* exception during load */ rb_exc_raise(th->ec->errinfo);
return TAG_RAISE;
} }
return state;
} }
static void static void
rb_load_internal(VALUE fname, int wrap) rb_load_internal(VALUE fname, int wrap)
{ {
rb_execution_context_t *ec = GET_EC(); rb_execution_context_t *ec = GET_EC();
int state = rb_load_internal0(ec, fname, wrap); rb_load_internal0(ec, fname, wrap);
if (state) {
if (state == TAG_RAISE) rb_exc_raise(ec->errinfo);
EC_JUMP_TAG(ec, state);
}
}
static VALUE
file_to_load(VALUE fname)
{
VALUE tmp = rb_find_file(FilePathValue(fname));
if (!tmp) load_failed(fname);
return tmp;
} }
void void
rb_load(VALUE fname, int wrap) rb_load(VALUE fname, int wrap)
{ {
rb_load_internal(file_to_load(fname), wrap); VALUE tmp = rb_find_file(FilePathValue(fname));
if (!tmp) load_failed(fname);
rb_load_internal(tmp, wrap);
} }
void void
rb_load_protect(VALUE fname, int wrap, int *pstate) rb_load_protect(VALUE fname, int wrap, int *pstate)
{ {
enum ruby_tag_type state; enum ruby_tag_type state;
volatile VALUE path = 0;
EC_PUSH_TAG(GET_EC()); EC_PUSH_TAG(GET_EC());
if ((state = EC_EXEC_TAG()) == TAG_NONE) { if ((state = EC_EXEC_TAG()) == TAG_NONE) {
path = file_to_load(fname); rb_load(fname, wrap);
} }
EC_POP_TAG(); EC_POP_TAG();
if (state == TAG_NONE) state = rb_load_internal0(GET_EC(), path, wrap);
if (state != TAG_NONE) *pstate = state; if (state != TAG_NONE) *pstate = state;
} }
@ -1025,7 +1006,7 @@ rb_require_internal(VALUE fname, int safe)
else { else {
switch (found) { switch (found) {
case 'r': case 'r':
state = rb_load_internal0(ec, path, 0); rb_load_internal(path, 0);
break; break;
case 's': case 's':
@ -1034,10 +1015,8 @@ rb_require_internal(VALUE fname, int safe)
rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
break; break;
} }
if (!state) { rb_provide_feature(path);
rb_provide_feature(path); result = TAG_RETURN;
result = TAG_RETURN;
}
} }
} }
} }

View file

@ -1671,6 +1671,19 @@ class TestSetTraceFunc < Test::Unit::TestCase
ary ary
end end
def test_single_raise_inside_load
events = []
tmpdir = Dir.mktmpdir
path = "#{tmpdir}/hola.rb"
File.open(path, "w") { |f| f.write("raise") }
TracePoint.new(:raise){|tp| next if !target_thread?; events << [tp.event]}.enable{
load path rescue nil
}
assert_equal [[:raise]], events
ensure
FileUtils.rmtree(tmpdir)
end
def f_raise def f_raise
raise raise
rescue rescue

2
vm.c
View file

@ -1487,7 +1487,6 @@ rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
return make_localjump_error(mesg, val, state); return make_localjump_error(mesg, val, state);
} }
#if 0
void void
rb_vm_jump_tag_but_local_jump(int state) rb_vm_jump_tag_but_local_jump(int state)
{ {
@ -1495,7 +1494,6 @@ rb_vm_jump_tag_but_local_jump(int state)
if (!NIL_P(exc)) rb_exc_raise(exc); if (!NIL_P(exc)) rb_exc_raise(exc);
EC_JUMP_TAG(GET_EC(), state); EC_JUMP_TAG(GET_EC(), state);
} }
#endif
static rb_control_frame_t * static rb_control_frame_t *
next_not_local_frame(rb_control_frame_t *cfp) next_not_local_frame(rb_control_frame_t *cfp)