[D-runtime] stacktraces on windows

Rainer Schuetze r.sagitario at gmx.de
Mon May 9 16:01:33 PDT 2011


Sean Kelly wrote:
> On May 7, 2011, at 5:05 AM, Rainer Schuetze wrote:
> 
>> Walter Bright wrote:
>>> when running unittests. Usually it just hangs.
>>> unittest
>>> totalCPUs = 2
>>> object.Error: Access Violation
>>> ----------------
>>> 62B6DC
>>> 62B553
>>> ----------------
>>> --- errorlevel 1
>> Hijacking this thread from the phobos list, I'd like to comment on stack traces under windows:
>>
>> - you'll never get a symbolic stacktrace without converting the debug info with cv2pdb (well, it might work for very simple executables). stacktrace.d uses dbghelp.dll, and this usually dislikes the debug information generated by dmd/optlink.
> 
> This has worked for me in testing, but those tests were with very simple executables.  Are there any alternatives?


I've read on Benjamin Thaut's page about his stacktrace implementation, 
that it depends on the version of dbghelp.dll, but without any exact 
version given. Maybe I'm outdated here, but judging from reports on the 
newsgroup, others seem to have the same problem.

> 
>> - if symbols are found, generating the stack trace message generates another exception inside std.demangle if the symbol cannot be demangled (non-D, compressed or SHA'd symbols).
> 
> If it helps, the exception thrown is a static exception, and is caught within demangle().  With the new chaining rules, this shouldn't adversely affect anything.


I've seen recursive exceptions in the debugger, but debugging only works 
after conversion of the debug info with cv2pdb, so it might be a little 
different. A recent change in dmd causes debug symbols to output 
demangled names, so using core.demangle should not be necessary anymore 
for printing the callstack.

> 
>> - walking the stack trace can be very time consuming, especially when loading debug symbols while doing so. This should not be done for every exception thrown.
> 
> What do you suggest?  I'd considered disabling tracing if -release was specified, though I haven't yet tested my idea for how to make this work.

As suggested for linux elsewhere, would it be possible to create the 
call stack only for unhandled exceptions or if requested by the 
exception handler? I remember doing this for SEH in C++, but don't have 
the details at the moment.

> 
>> - the stack trace often misses the source file location where the exception is thrown as reported here: http://d.puremagic.com/issues/show_bug.cgi?id=4809
>> I'm not sure the patch is up to date, though.
> 
> Patch?  The code is already in druntime.  Or am I missing something?  Look at core.runtime and core.sys.windows.dbghelp.

The patch consists of adding option -S to the dmc command line when 
compiling deh.c, so it does not omit frame pointers. Otherwise the usual 
stack walk skips functions and has problems resyncing the frame pointer 
positions. See also http://www.dsource.org/projects/visuald/ticket/13 - 
I assume the VS debugger does the same as dbghelp.dll here.
In the meantime the exception handling has been moved to a D 
implementation deh.d, but the problem seems to remain the same: the 
location that actually does the throw is often missing. I'll try to 
figure out if it is still the same cause.

>> - a convenient way to inspect crashes is to fire up the debugger when the crash happens with the crash reporting by Windows. This functionality is currently blocked by dmain2.main() handling all Exceptions (which also lets a non-console application blow up without any message). Also, stopping on unhandled exceptions only inside a debugger is not possible.
>> I understand that a dialog showing up is no good when running programs from the console (e.g. the autotester), so I suggest making this configurable:
>>
>> a: catch all Throwables
>> b: catch all Exceptions
>> c: catch none
>>
>> There's already a variable rt_trapExceptions available that does a or c, but you can't configure it before executing the program. It is also copied to a local value before any static initializer is called, so it cannot be modified programmatically. (The comment says it should be modified by the debugger, but I don't think this is a sensible approach.)
> 
> DDBG always worked this way.  In fact, I believe it was added on request from the developer.  I'd be happy to get rid of it if someone can suggest a better alternative though.

A first step would be to allow setting rt_trapExceptions from a static 
constructor, so you can configure how exceptions in main() are handled. 
This currently does not work because rt_trapExceptions is copied to a 
local variable trapExceptions before running the constructors.

I'm not sure how to access rt_trapExceptions earlier so it will also 
affect static constructors and unittests. Maybe it could be set from an 
environment variable.


More information about the D-runtime mailing list