# Thead.parent, revisited. Or: Building a call stack

**URL:** <https://www.ruby-forum.com/t/thead-parent-revisited-or-building-a-call-stack/87739>\
**Category:** Ruby\
**Created:** [March 5, 2007, 6:07pm UTC](https://www.ruby-forum.com/t/thead-parent-revisited-or-building-a-call-stack/87739 "2007-03-05T18:07:17Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![erikveen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/59ef9b/32.png) [@erikveen](https://www.ruby-forum.com/u/erikveen)\
**Post date:** [March 5, 2007, 6:07pm UTC](https://www.ruby-forum.com/t/thead-parent-revisited-or-building-a-call-stack/87739/1 "2007-03-05T18:07:17Z")

</div>

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/](http://www.erikveen.dds.nl/)

---

<div class="post-metadata">

**Author:** ![erikveen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/59ef9b/32.png) [@erikveen](https://www.ruby-forum.com/u/erikveen)\
**Post date:** [March 5, 2007, 7:19pm UTC](https://www.ruby-forum.com/t/thead-parent-revisited-or-building-a-call-stack/87739/2 "2007-03-05T19:19:30Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![erikveen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/59ef9b/32.png) [@erikveen](https://www.ruby-forum.com/u/erikveen)\
**Post date:** [March 5, 2007, 7:56pm UTC](https://www.ruby-forum.com/t/thead-parent-revisited-or-building-a-call-stack/87739/3 "2007-03-05T19:56:35Z")

</div>

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/](http://www.erikveen.dds.nl/)

[1] [http://tinyurl.com/38823g](http://tinyurl.com/38823g)

---

<div class="post-metadata">

**Author:** ![erikveen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/59ef9b/32.png) [@erikveen](https://www.ruby-forum.com/u/erikveen)\
**Post date:** [March 5, 2007, 9:41pm UTC](https://www.ruby-forum.com/t/thead-parent-revisited-or-building-a-call-stack/87739/4 "2007-03-05T21:41:53Z")

</div>

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
