[ruby-core:25831] event hook in 1.9?

4 views
Skip to first unread message

Ryan Davis

unread,
Sep 29, 2009, 3:21:24 AM9/29/09
to ruby...@ruby-lang.org
> /**
> @c setting
> @e trace
> @j trace 用の命令。
> */
> DEFINE_INSN
> trace
> (rb_num_t nf)
> ()
> ()
> {
> rb_event_flag_t flag = (rb_event_flag_t)nf;
>
> EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */);
> }

Am I missing something? Does this TODO imply that the event hook
mechanism isn't supposed to work yet?


Mark Moseley

unread,
Sep 29, 2009, 4:03:35 AM9/29/09
to ruby...@ruby-lang.org

The hook works fine, it just doesn't pass in the id and klass variables.
You can get them pretty easily, though
(ruby_current_thread->cfp->iseq->defined_method_id and
ruby_current_thread->cfp->iseq->klass).

Mark


Rocky Bernstein

unread,
Sep 29, 2009, 4:43:46 AM9/29/09
to ruby...@ruby-lang.org
The event hook definitely works.

The TODO relates I think to setting id and klass which I what 1.8 does.

begin long discussion which most may want to ignore:

That said, in my view I don't believe it necessary to ever fill this out. Instead what I'd rather see is the event hook call interface simplified.

Right now it is a trace function call looks like:
  trace_function(event, file, line, id, bind, klass)

What I've been using in an experimental debugger is:
   trace_function(event, frame, arg=nil)

From frame you can figure out file, line, id, bind and so on. I was thinking that in the replacement call arg would be a placeholder for any event where it may be desirable to pass more information. For example the return value in a function or perhaps exception information in a raise. I think this is how Python does it in their trace hook.

(Right now the way I up a value about to be returned is by just retrieving the value from the VM stack which is very YARV specific).

As for file and line, I find this a little weird. The intent clearly is to indicate a source position of where you are at when the event triggers. But even though there are two (unnecessary in my opinion) parameters, it still falls short of being specific and general.

"file" sometimes might not be a file if say you are running the internal_prelude in a require ;-)
So I use a notion of a  "container" which is a two part thing: one part is something like a locator ("file") and the other the object in which that locator lives. Many times the locator is a "file" inside say a filesystem,  but it could be a string variable passed to eval or RubyVM::InstructionSequenceCompile.
 
So here it may be helpful say in a debugger or trace hook routine to know not only the position of the text inside that variable but perhaps the location of the eval. That way you could set the frame to be the context of the eval on the call stack and pick up the full source text of the eval which by the way doesn't appear in SCRIPT_LINES__.

In Python where packages can be bundled inside "egg" files and sometimes compressed,  you might want to indicate that "file" is not in a filesystem but inside this bundled file.

And as for "line", well, in the general case I think one wants again a two-part thing: both a start position and and end position which would be a starting "line" offset and a character offset within that and then an ending line and an ending-line character offset. Right now I don't believe Ruby will ever allow a compilation to start in one container (or "file") and end in another, so repeating the "file" part on the end is not needed.

However in the presence of optimization, it is conceivable that instructions or source code fragments from different "lines" get combined. So in fact there may be several sets of positions for say a given VM instruction or stopping place.  So what I have here is an unstructured array of "positions", each position being in general a two part thingy, but for now I just have a single Fixnum "line".

Some of these thoughts I have documented in  http://github.com/rocky/rb-threadframe/blob/master/threadframe.rd which is in need of update.

Rocky Bernstein

unread,
Sep 29, 2009, 5:00:37 AM9/29/09
to ruby...@ruby-lang.org

That C code is easy? To each his/her own.

This works if there is an instruction sequence associated with the stopping point. If not, the binding parameter of the trace hook call may be useful to get the class.

If you are inside a VM C frame (like "times" or "upto"  there is no VM instruction sequence, the method name is recorded, but you need to get at via other means since C frames don't have iseq's.


Mark



Ryan Davis

unread,
Sep 29, 2009, 5:58:40 AM9/29/09
to ruby...@ruby-lang.org

On Sep 29, 2009, at 01:03 , Mark Moseley wrote:

> Ryan Davis wrote:
>>> /**
>>> @c setting
>>> @e trace
>>> @j trace 用の命令。
>>> */
>>> DEFINE_INSN
>>> trace
>>> (rb_num_t nf)
>>> ()
>>> ()
>>> {
>>> rb_event_flag_t flag = (rb_event_flag_t)nf;
>>>
>>> EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass
>>> */);
>>> }
>>
>> Am I missing something? Does this TODO imply that the event hook
>> mechanism isn't supposed to work yet?
>>
>>
>>
>>
>
> The hook works fine, it just doesn't pass in the id and klass

> variables. [...]

No... "works fine" for me means "compatible" and this definitely
isn't. My event_hook gem has had to go through a lot of convolutions
just to compile and now it turns out that it is going to need even
more to work as it did before.


Mark Moseley

unread,
Sep 29, 2009, 8:47:25 AM9/29/09
to ruby...@ruby-lang.org
Well, you asked about "supposed to work". I think that the answer to
that is yes. But no, it's not backwards-compatible at all with 1.8. I
would also say that the more that I dig into the Ruby VM the more I like
it. To each his own, though, as you pointed out.


Ryan Davis

unread,
Sep 29, 2009, 10:57:45 PM9/29/09
to ruby...@ruby-lang.org

On Sep 29, 2009, at 01:03 , Mark Moseley wrote:

> The hook works fine, it just doesn't pass in the id and klass
> variables. You can get them pretty easily, though
> (ruby_current_thread->cfp->iseq->defined_method_id and
> ruby_current_thread->cfp->iseq->klass).

Neither ruby_current_thread nor rb_thread_t are defined as public, so
I don't see how this is possible (and safe/maintainable). They appear
to be in the private vm_core.h at the base of trunk/1_9.

It seems to me that the TODO that I pointed out needs to be finished
for event_hook to be usable.

Koichi, are there any plans for this?


Mark Moseley

unread,
Sep 29, 2009, 11:02:26 PM9/29/09
to ruby...@ruby-lang.org
ruby-debug19 relies on this, and is working fairly well, so it's clearly
possible. It would be good if Koichi would address the safe/maintainable
question, though; that's a good point.


Ryan Davis

unread,
Sep 29, 2009, 11:41:30 PM9/29/09
to ruby...@ruby-lang.org

No. ruby-debug19(-base) relies on your ruby_core_source gem... I don't
think that a hack of that magnitude qualifies as "working fairly
well". I'd rather write code that works out of the box with the
version of ruby I'm using.

Further, I don't think your solution is safe. Is there any guarantee
that threads won't switch between the time that the event is generated
and the event_hook is called? There is a LOT of mechanism in there
and I can't wade through that question (and don't trust it as a result).


Mark Moseley

unread,
Sep 30, 2009, 12:09:24 AM9/30/09
to ruby...@ruby-lang.org
Ryan Davis wrote:
>
> On Sep 29, 2009, at 20:02 , Mark Moseley wrote:
>
>> Ryan Davis wrote:
>>>
>>> On Sep 29, 2009, at 01:03 , Mark Moseley wrote:
>>>
>>>> The hook works fine, it just doesn't pass in the id and klass
>>>> variables. You can get them pretty easily, though
>>>> (ruby_current_thread->cfp->iseq->defined_method_id and
>>>> ruby_current_thread->cfp->iseq->klass).
>>>
>>> Neither ruby_current_thread nor rb_thread_t are defined as public,
>>> so I don't see how this is possible (and safe/maintainable). They
>>> appear to be in the private vm_core.h at the base of trunk/1_9.
>>>
>>> It seems to me that the TODO that I pointed out needs to be finished
>>> for event_hook to be usable.
>>>
>>> Koichi, are there any plans for this?
>>>
>> ruby-debug19 relies on this, and is working fairly well, so it's
>> clearly possible. It would be good if Koichi would address the
>> safe/maintainable question, though; that's a good point.

>
> No. ruby-debug19(-base) relies on your ruby_core_source gem... I don't
> think that a hack of that magnitude qualifies as "working fairly
> well". I'd rather write code that works out of the box with the
> version of ruby I'm using.
>
> Further, I don't think your solution is safe. Is there any guarantee
> that threads won't switch between the time that the event is generated
> and the event_hook is called? There is a LOT of mechanism in there
> and I can't wade through that question (and don't trust it as a result).
>
>
>
Fair enough. Then the answer to your question is no, using the hook is
not possible, and probably never will be.

To answer your thread switching concern: there's one method between the
VM executing the bytecode in vm_exec_core() and my hook
(exec_event_hooks). It doesn't touch ruby_current_thread. Not much
mechanism at all; it seems very safe to me, and I have spent hours and
hours debugging the VM. Also, as a side note, the debugger suspends all
running threads. It's conceivable to me that there are potential race
conditions that might cause problems, though.

Further, in practice, I am not getting any bug reports of segfaults
under the debugger that I have not already attributed to other issues;
and all such problems are fixed. If you're not comfortable with the
induction, fine, but to me, that means something.


SASADA Koichi

unread,
Jan 22, 2010, 8:10:36 PM1/22/10
to ruby...@ruby-lang.org, Ryan Davis
(2009/09/30 11:57), Ryan Davis wrote::
> Koichi, are there any plans for this?

Sorry for my late response. I'm processing over 2000 unread message on
ruby-core and I find this post now.

I want to provide stack frame traversing "C" API that you can access
frame information such as RECEIVER, CALLEE METHOD NAME, and so on. In
our laboratory, prototype was finished (for memory profiler, that
Soh-san posted).

Is this enough for your use?

--
// SASADA Koichi at atdot dot net

Reply all
Reply to author
Forward
0 new messages