Getting a full backtrace from Thread#join?

Here’s a program that demonstrates some unhelpful output:

def countdown(n)
if n == 0
raise Exception.new
else
countdown(n-1)
end
end

a = Thread.new { countdown(5) }

begin
a.join
rescue Exception => ex
print “#{ex}\n"
print ex.backtrace.join(”\n")
print "\n"
end

The backtrace I see looks like this:

Exception
bt:3:in countdown' bt:12:injoin’
bt:12

Problem is that only the first line of the backtrace belongs to the thread
which threw the exception (whereas I should see 5 nested calls to
’countdown’). I’m trying to weed out an exception in a multithreaded
application and one line of backtrace isn’t enough; is there any way of
getting hold of the thread’s full backtrace?

···


Matthew

Matthew Bloch wrote:

Here’s a program that demonstrates some unhelpful output:

def countdown(n)
if n == 0
raise Exception.new
else
countdown(n-1)
end
end

a = Thread.new { countdown(5) }

begin
a.join
rescue Exception => ex
print “#{ex}\n”
print ex.backtrace.join(“\n”)
print “\n”
end

The backtrace I see looks like this:

Exception
bt:3:in countdown' bt:12:in join’
bt:12

Problem is that only the first line of the backtrace belongs to the thread
which threw the exception (whereas I should see 5 nested calls to
‘countdown’). I’m trying to weed out an exception in a multithreaded
application and one line of backtrace isn’t enough; is there any way of
getting hold of the thread’s full backtrace?

Has anyone got a better solution than overriding Thread and using this kind
of setup?

class EThread < Thread
def initialize(*args)
super(*args) do |a|
begin
yield(*a)
rescue Exception => e
# deal with exception here, not outside

···

    Log.error "thread #{self} exception '#{e.type} : #{e.message}'"     
    Log.backtrace(e)
    raise
  end
end

end
end


Matthew