-
-
Notifications
You must be signed in to change notification settings - Fork 416
Issue 4809: Help the stack walker to find the location of a throw statement #80
Conversation
Just thought about this again. Maybe adding the additional stack entries could be limited to debug builds of the executable by checking the image header for a debug directory entry. (I think this should also be done for generating stack traces in exceptions and loading dbghelp.dll). |
I also noticed that the stack trace generation allocates an even larger buffer on the stack (char[2048] demangleBuf;) in addition to some rather large structs (e.g. CONTEXT), so it should not hurt to use the same stack space a little later. |
dec EAX; | ||
jnz clear_stack; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reasoning for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reasoning for this?
Without full debug information (including symbols from the Microsoft
symbol sever) the stack walker used by the stack tracing and the
debugger often misses the function on the stack that actually invokes
_d_throw.
My guess is: as there is usually no debug info for both the system DLLs
involved and the D runtime library, the stack walker finds the calling
function by searching addresses on the stack that point to possible code
segments, but somehow skips the missing return address.
The patch fills the stack with zeroes to resynchronize the stack walker,
assuming it starts simply scanning the stack when it it finds a block of
zeroes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why scanning? StackWalk64 could do normal return address/frame pointer unwinding.
You can try to instrument the ReadMemoryRoutine parameter of StackWalk64 to trace
why this fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are often no frame pointers, so the stack walker only works
correctly with debug info that has frame pointer omission info.
I wasn't aware of the read callback, it might give a hint to improve the
patch...
BTW, personally I think we should just have debug and release Phobos+Druntime libs, and make use of the -debuglib DMD option. The release libs can get |
{ | ||
naked; | ||
push EBP; | ||
mov EBP,ESP; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space after comma :o)
Issue 4809: Help the stack walker to find the location of a throw statement
I think we should revert this.
|
The forced stack frame helps, I guess you do not object to this, but the strange push-loop. I agree that pushing a lot of zeroes on the stack to hope for some better behaviour by the OS feels like a dirty hack, but if it helps... I'll keep an eye on it if it does actually have the expected benefit.
What about the issue in the bug report? The stack trace is already improved by the forced stack frame. Looking at the call stack inside the debugger is a bit harder to automate for a test case.
I just rechecked: the traceNoSync call uses about 6kB of stack. As mentioned in the discussion, 400 words instead of 1000 seem fine aswell.
Taking a snapshot of the stack with resolving debug symbols indicates that performance is not an issue at all ;-)
Yeah, it looks much better now. Still I want a simple way to disable it (included its shared static this()) because it does not help when running in a debugger. |
Right, I missed the bug report when I wrote this.
So Runtime.traceHandler won't help you? |
To some extend it does, but it does not prevent the loading of
Maybe it works to delay the stack trace generation into the outermost |
Sounds reasonable. |
"_d_exception_filter" does not seem to be used at all, but I have tried something similar that seems to work: create a new class StackTraceThrowable deriving from Throwable, use it in the catch handler that wants the stack trace, and check for it in _d_framehandler. Then, generate the stack trace only If it is the searched exception, but continue as if a Throwable has been passed. |
This patch creates a standard stack frame for the _d_thowc function under Windowsn, even if druntime is built in release mode. This allows the stack dump and a debugger to display a correct call stack when an exception is thrown.
In addition, a workaround is added to allow the stack walker to synchronize without symbols for kernel32/kernelbase being available.
http://d.puremagic.com/issues/show_bug.cgi?id=4809