* vm_core.h (rb_vm_t::trace_running): add a new field

`trace_running' to store vm global tracing status.

* vm_trace.c: fix SEGV bug. event_hook was free'd
  even when the hook is still used in another thread.
  [ruby-dev:46141] [Bug #7032]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37280 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ktsj 2012-10-21 10:14:26 +00:00
Родитель 93184600c8
Коммит f21d7d9831
3 изменённых файлов: 20 добавлений и 4 удалений

Просмотреть файл

@ -1,3 +1,12 @@
Sun Oct 21 19:12:59 2012 Kazuki Tsujimoto <kazuki@callcc.net>
* vm_core.h (rb_vm_t::trace_running): add a new field
`trace_running' to store vm global tracing status.
* vm_trace.c: fix SEGV bug. event_hook was free'd
even when the hook is still used in another thread.
[ruby-dev:46141] [Bug #7032]
Sun Oct 21 19:12:42 2012 Kazuki Tsujimoto <kazuki@callcc.net>
* vm_core.h (rb_vm_t::trace_flag): remove `trace_flag'

Просмотреть файл

@ -343,6 +343,7 @@ typedef struct rb_vm_struct {
int running;
int inhibit_thread_creation;
int thread_abort_on_exception;
int trace_running;
volatile int sleeper;
/* object management */

Просмотреть файл

@ -268,12 +268,12 @@ clean_hooks(rb_hook_list_t *list)
}
static int
exec_hooks(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg)
exec_hooks(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg, int can_clean_hooks)
{
int state;
volatile int raised;
if (UNLIKELY(list->need_clean > 0)) {
if (UNLIKELY(list->need_clean > 0) && can_clean_hooks) {
clean_hooks(list);
}
@ -310,10 +310,12 @@ rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t event, VALUE self
{
if (th->trace_running == 0 &&
self != rb_mRubyVMFrozenCore /* skip special methods. TODO: remove it. */) {
int vm_tracing = th->vm->trace_running;
int state = 0;
int outer_state = th->state;
th->state = 0;
th->vm->trace_running = 1;
th->trace_running = 1;
{
const VALUE errinfo = th->errinfo;
@ -330,20 +332,21 @@ rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t event, VALUE self
/* thread local traces */
list = &th->event_hooks;
if (list->events & event) {
state = exec_hooks(th, list, &ta);
state = exec_hooks(th, list, &ta, TRUE);
if (state) goto terminate;
}
/* vm global traces */
list = &th->vm->event_hooks;
if (list->events & event) {
state = exec_hooks(th, list, &ta);
state = exec_hooks(th, list, &ta, !vm_tracing);
if (state) goto terminate;
}
th->errinfo = errinfo;
}
terminate:
th->trace_running = 0;
th->vm->trace_running = vm_tracing;
if (state) {
TH_JUMP_TAG(th, state);
@ -360,8 +363,10 @@ rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg)
VALUE result = Qnil;
rb_thread_t *th = GET_THREAD();
int state;
int vm_tracing = th->vm->trace_running;
int tracing = th->trace_running;
th->vm->trace_running = 1;
th->trace_running = 1;
raised = rb_threadptr_reset_raised(th);
outer_state = th->state;
@ -377,6 +382,7 @@ rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg)
rb_threadptr_set_raised(th);
}
th->trace_running = tracing;
th->vm->trace_running = vm_tracing;
if (state) {
JUMP_TAG(state);