This project is closed and read-only.
Backport #7624 ยป 193backport_exception_in_settracefunc.patch
| bootstraptest/test_flow.rb (working copy) | ||
|---|---|---|
|
assert_equal "false", src + %q{e.all? {false}}, bug
|
||
|
assert_equal "true", src + %q{e.include?(:foo)}, bug
|
||
|
end
|
||
|
assert_equal('ok', %q{
|
||
|
class FOO < RuntimeError; end
|
||
|
class BAR < RuntimeError; end
|
||
|
def m
|
||
|
raise FOO
|
||
|
end
|
||
|
set_trace_func(proc{|t,| raise BAR if t == 'return'})
|
||
|
begin
|
||
|
m
|
||
|
rescue BAR
|
||
|
'ok'
|
||
|
end
|
||
|
}, '[ruby-core:51128] [ruby-trunk - Bug #7624]')
|
||
| vm_core.h (working copy) | ||
|---|---|---|
|
/* tracer */
|
||
|
void
|
||
|
rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t flag, VALUE self, ID id, VALUE klass);
|
||
|
rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t flag, VALUE self, ID id, VALUE klass, int pop_p);
|
||
|
#define EXEC_EVENT_HOOK(th, flag, self, id, klass) do { \
|
||
|
#define EXEC_EVENT_HOOK_ORIG(th, flag, self, id, klass, pop_p) do { \
|
||
|
rb_event_flag_t wait_event__ = (th)->event_flags; \
|
||
|
if (UNLIKELY(wait_event__)) { \
|
||
|
if (wait_event__ & ((flag) | RUBY_EVENT_VM)) { \
|
||
|
rb_threadptr_exec_event_hooks((th), (flag), (self), (id), (klass)); \
|
||
|
rb_threadptr_exec_event_hooks((th), (flag), (self), (id), (klass), (pop_p)); \
|
||
|
} \
|
||
|
} \
|
||
|
} while (0)
|
||
|
#define EXEC_EVENT_HOOK(th, flag, self, id, klass) \
|
||
|
EXEC_EVENT_HOOK_ORIG(th, flag, self, id, klass, 0)
|
||
|
#define EXEC_EVENT_HOOK_AND_POP_FRAME(th, flag, self, id, klass) \
|
||
|
EXEC_EVENT_HOOK_ORIG(th, flag, self, id, klass, 1)
|
||
|
#if defined __GNUC__ && __GNUC__ >= 4
|
||
|
#pragma GCC visibility push(default)
|
||
| thread.c (working copy) | ||
|---|---|---|
|
EVENT_RUNNING_EVENT_MASK = EVENT_RUNNING_VM|EVENT_RUNNING_THREAD
|
||
|
};
|
||
|
static VALUE thread_suppress_tracing(rb_thread_t *th, int ev, VALUE (*func)(VALUE, int), VALUE arg, int always);
|
||
|
static VALUE thread_suppress_tracing(rb_thread_t *th, int ev, VALUE (*func)(VALUE, int), VALUE arg, int always, int pop_p);
|
||
|
struct event_call_args {
|
||
|
rb_thread_t *th;
|
||
| ... | ... | |
|
static inline int
|
||
|
exec_event_hooks(const rb_event_hook_t *hook, rb_event_flag_t flag, VALUE self, ID id, VALUE klass)
|
||
|
{
|
||
|
volatile int removed = 0;
|
||
|
const rb_event_hook_t *volatile hnext = 0;
|
||
|
int state;
|
||
|
PUSH_TAG();
|
||
|
if ((state = EXEC_TAG()) != 0) {
|
||
|
hook = hnext;
|
||
|
}
|
||
|
int removed = 0;
|
||
|
for (; hook; hook = hook->next) {
|
||
|
if (hook->flag & RUBY_EVENT_REMOVED) {
|
||
|
removed++;
|
||
|
continue;
|
||
|
}
|
||
|
if (flag & hook->flag) {
|
||
|
hnext = hook->next;
|
||
|
(*hook->func)(flag, hook->data, self, id, klass);
|
||
|
}
|
||
|
}
|
||
|
POP_TAG();
|
||
|
return removed;
|
||
|
}
|
||
| ... | ... | |
|
}
|
||
|
void
|
||
|
rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t flag, VALUE self, ID id, VALUE klass)
|
||
|
rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t flag, VALUE self, ID id, VALUE klass, int pop_p)
|
||
|
{
|
||
|
const VALUE errinfo = th->errinfo;
|
||
|
struct event_call_args args;
|
||
| ... | ... | |
|
args.id = id;
|
||
|
args.klass = klass;
|
||
|
args.proc = 0;
|
||
|
thread_suppress_tracing(th, EVENT_RUNNING_EVENT_MASK, thread_exec_event_hooks, (VALUE)&args, FALSE);
|
||
|
thread_suppress_tracing(th, EVENT_RUNNING_EVENT_MASK, thread_exec_event_hooks, (VALUE)&args, FALSE, pop_p);
|
||
|
th->errinfo = errinfo;
|
||
|
}
|
||
| ... | ... | |
|
ruby_suppress_tracing(VALUE (*func)(VALUE, int), VALUE arg, int always)
|
||
|
{
|
||
|
rb_thread_t *th = GET_THREAD();
|
||
|
return thread_suppress_tracing(th, EVENT_RUNNING_TRACE, func, arg, always);
|
||
|
return thread_suppress_tracing(th, EVENT_RUNNING_TRACE, func, arg, always, 0);
|
||
|
}
|
||
|
static VALUE
|
||
|
thread_suppress_tracing(rb_thread_t *th, int ev, VALUE (*func)(VALUE, int), VALUE arg, int always)
|
||
|
thread_suppress_tracing(rb_thread_t *th, int ev, VALUE (*func)(VALUE, int), VALUE arg, int always, int pop_p)
|
||
|
{
|
||
|
int state, tracing = th->tracing, running = tracing & ev;
|
||
|
volatile int raised;
|
||
| ... | ... | |
|
th->tracing = tracing;
|
||
|
if (state) {
|
||
|
if (pop_p) {
|
||
|
th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
|
||
|
}
|
||
|
JUMP_TAG(state);
|
||
|
}
|
||
|
th->state = outer_state;
|
||
| KNOWNBUGS.rb (working copy) | ||
|---|---|---|
|
# So all tests will cause failure.
|
||
|
#
|
||
|
assert_equal('', "set_trace_func(proc{|t,|raise if t == 'line'})\n""1\n'ok'")
|
||
|
assert_finish(3, "def m; end\n""set_trace_func(proc{|t,|raise if t == 'return'})\n""m")
|
||
| vm.c (working copy) | ||
|---|---|---|
|
switch (VM_FRAME_TYPE(th->cfp)) {
|
||
|
case VM_FRAME_MAGIC_METHOD:
|
||
|
EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, th->cfp->self, 0, 0);
|
||
|
EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_RETURN, th->cfp->self, 0, 0);
|
||
|
break;
|
||
|
case VM_FRAME_MAGIC_CLASS:
|
||
|
EXEC_EVENT_HOOK(th, RUBY_EVENT_END, th->cfp->self, 0, 0);
|
||
|
EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_END, th->cfp->self, 0, 0);
|
||
|
break;
|
||
|
}
|
||