Forum: Ruby Thead.parent, revisited. Or: Building a call stack.

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Erik V. (Guest)
on 2007-03-05 19:07
(Received via mailing list)
In order to build a diagram of all method calls in an
application, I created a set_trace_func function. This function
builds a call stack. Each thread in each process should have
its own call stack, initialized to the call stack of the parent
process or the parent thread.

The call stacks are stored in the array stack_per_thread. The
initial call stack is an empty array:

 stack_per_thread = []
 stack_per_thread[[Process.pid, Thread.current]] = []

Creating a new call stack after a fork (both process fork and
thread fork) is done like this:

 stack = (stack_per_thread[[Process.pid, Thread.current]] ||=
stack.dup)

Process forks are not a problem, since the last call stack
before the process fork is the one with which the child process
has to continue and does continue.

However, threads are a bit of a problem. Threads don't have a
parent, which means that it's not possible to clone the call
stack of the parent thread. I currently fake the concept
"parent thread" by assuming that the last running thread is the
parent thread.

If Parent.thread existed, everything would be perfectly fine:

 stack = (stack_per_thread[[Process.pid, Thread.current]] ||=
          stack_per_thread[[Process.pid, Thread.parent]].dup)

I observed a couple of traces and noticed, empirically, that a
new thread always gets a couple of CPU cycles (and hence calls
to set_trace_func). If this is always true, my assumption ("the
last thread is the parent thread") is no problem. If the parent
process can spawn many threads before any of them gets some CPU
cycles, well, then we do have a problem... :{

Ideas? Related work? Anybody able to understand the C code?
Matz?... :}

gegroet,
Erik V. - http://www.erikveen.dds.nl/
unknown (Guest)
on 2007-03-05 20:19
(Received via mailing list)
On Tue, 6 Mar 2007, Erik V. wrote:

> stack_per_thread[[Process.pid, Thread.current]] = []
>
>
> I observed a couple of traces and noticed, empirically, that a
> new thread always gets a couple of CPU cycles (and hence calls
> to set_trace_func). If this is always true, my assumption ("the
> last thread is the parent thread") is no problem. If the parent
> process can spawn many threads before any of them gets some CPU
> cycles, well, then we do have a problem... :{
>
> Ideas? Related work? Anybody able to understand the C code?
> Matz?... :}

class Thread
   class << self
     alias_method "__new__", "new"
     def new *a, &b
       child '__new__', *a, &b
     end
     alias_method "__start__", "start"
     def start *a, &b
       child '__start__', *a, &b
     end
   private
     def child as, *a, &b
       parent = Thread.current
       send(as, *a) do |*a|
         Thread.current.parent = parent
         b.call *a
       end
     end
   end
   def parent
     self['parent']
   end
   def parent= parent
     self['parent'] = parent
   end
   def ancestors
     return self['ancestors'] if self['ancestors']
     list = [t = self]
     while((t = t.parent))
       list << t
     end
     self['ancestors'] = list
   end
end


-a
Erik V. (Guest)
on 2007-03-05 20:56
(Received via mailing list)
Yep, I know. That's a "work around". But, as we've discussed
before [1], it's not water tight.

"Thread#start doesn't reuse Thread.new. Neither does
rb_thread_create(), which is used in e.g. TK."

Thanks.

gegroet,
Erik V. - http://www.erikveen.dds.nl/

 [1] http://tinyurl.com/38823g
unknown (Guest)
on 2007-03-05 22:41
(Received via mailing list)
On Tue, 6 Mar 2007, Erik V. wrote:

> Yep, I know. That's a "work around". But, as we've discussed
> before [1], it's not water tight.
>
> "Thread#start doesn't reuse Thread.new. Neither does
> rb_thread_create(), which is used in e.g. TK."

oh right.  forgot.

check out ThreadGroup - i think it's properties may allow someone to
hack what
you're after.  just looking at that today - but out of time now...

-a
This topic is locked and can not be replied to.