Bug #15885 » 0001-Single-raise-tracepoint-event-when-exception-inside-.patch
| eval_intern.h | ||
|---|---|---|
| 
     NORETURN(void rb_print_undef_str(VALUE, VALUE)); 
   | 
||
| 
     NORETURN(void rb_print_inaccessible(VALUE, ID, rb_method_visibility_t)); 
   | 
||
| 
     NORETURN(void rb_vm_localjump_error(const char *,VALUE, int)); 
   | 
||
| 
     #if 0 
   | 
||
| 
     NORETURN(void rb_vm_jump_tag_but_local_jump(int)); 
   | 
||
| 
     #endif 
   | 
||
| 
     VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val); 
   | 
||
| 
     rb_cref_t *rb_vm_cref(void); 
   | 
||
| load.c | ||
|---|---|---|
| 
     NORETURN(static void load_failed(VALUE)); 
   | 
||
| 
     static int 
   | 
||
| 
     static inline void 
   | 
||
| 
     rb_load_internal0(rb_execution_context_t *ec, VALUE fname, int wrap) 
   | 
||
| 
     { 
   | 
||
| 
         enum ruby_tag_type state; 
   | 
||
| ... | ... | |
| 
         th->top_wrapper = wrapper; 
   | 
||
| 
         if (state) { 
   | 
||
| 
     	/* usually state == TAG_RAISE only, except for 
   | 
||
| 
     	 * 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; 
   | 
||
| 
             rb_vm_jump_tag_but_local_jump(state); 
   | 
||
| 
         } 
   | 
||
| 
         if (!NIL_P(th->ec->errinfo)) { 
   | 
||
| 
     	/* exception during load */ 
   | 
||
| 
     	return TAG_RAISE; 
   | 
||
| 
             rb_exc_raise(th->ec->errinfo); 
   | 
||
| 
         } 
   | 
||
| 
         return state; 
   | 
||
| 
     } 
   | 
||
| 
     static void 
   | 
||
| 
     rb_load_internal(VALUE fname, int wrap) 
   | 
||
| 
     { 
   | 
||
| 
         rb_execution_context_t *ec = GET_EC(); 
   | 
||
| 
         int state = 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; 
   | 
||
| 
         rb_load_internal0(ec, fname, wrap); 
   | 
||
| 
     } 
   | 
||
| 
     void 
   | 
||
| 
     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 
   | 
||
| 
     rb_load_protect(VALUE fname, int wrap, int *pstate) 
   | 
||
| 
     { 
   | 
||
| 
         enum ruby_tag_type state; 
   | 
||
| 
         volatile VALUE path = 0; 
   | 
||
| 
         EC_PUSH_TAG(GET_EC()); 
   | 
||
| 
         if ((state = EC_EXEC_TAG()) == TAG_NONE) { 
   | 
||
| 
     	path = file_to_load(fname); 
   | 
||
| 
             rb_load(fname, wrap); 
   | 
||
| 
         } 
   | 
||
| 
         EC_POP_TAG(); 
   | 
||
| 
         if (state == TAG_NONE) state = rb_load_internal0(GET_EC(), path, wrap); 
   | 
||
| 
         if (state != TAG_NONE) *pstate = state; 
   | 
||
| 
     } 
   | 
||
| ... | ... | |
| 
     	    else { 
   | 
||
| 
     		switch (found) { 
   | 
||
| 
     		  case 'r': 
   | 
||
| 
     		    state = rb_load_internal0(ec, path, 0); 
   | 
||
| 
     		    rb_load_internal(path, 0); 
   | 
||
| 
     		    break; 
   | 
||
| 
     		  case 's': 
   | 
||
| ... | ... | |
| 
     		    rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); 
   | 
||
| 
     		    break; 
   | 
||
| 
     		} 
   | 
||
| 
     		if (!state) { 
   | 
||
| 
     		    rb_provide_feature(path); 
   | 
||
| 
     		    result = TAG_RETURN; 
   | 
||
| 
     		} 
   | 
||
| 
                     rb_provide_feature(path); 
   | 
||
| 
                     result = TAG_RETURN; 
   | 
||
| 
     	    } 
   | 
||
| 
     	} 
   | 
||
| 
         } 
   | 
||
| test/ruby/test_settracefunc.rb | ||
|---|---|---|
| 
         ary 
   | 
||
| 
       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 
   | 
||
| 
         raise 
   | 
||
| 
       rescue 
   | 
||
| vm.c | ||
|---|---|---|
| 
         return make_localjump_error(mesg, val, state); 
   | 
||
| 
     } 
   | 
||
| 
     #if 0 
   | 
||
| 
     void 
   | 
||
| 
     rb_vm_jump_tag_but_local_jump(int state) 
   | 
||
| 
     { 
   | 
||
| ... | ... | |
| 
         if (!NIL_P(exc)) rb_exc_raise(exc); 
   | 
||
| 
         EC_JUMP_TAG(GET_EC(), state); 
   | 
||
| 
     } 
   | 
||
| 
     #endif 
   | 
||
| 
     static rb_control_frame_t * 
   | 
||
| 
     next_not_local_frame(rb_control_frame_t *cfp) 
   | 
||