www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.internals - Dlang structured exception handling on Windows

reply KytoDragon <kytodragon e.mail.de> writes:
I currently have a problem i don't know how to fix:

Programms compiled in D (either compiler) have the annoying 
property that they absorb all windows seh-exceptions, print the 
error code and terminate the process.

For example, the following programm will print "Program exited 
with code -1073741819" and exit:

module test.Test;

void main() {
     *cast(int*)cast(void*)0 = 1;
}

But what I expected was the following:

https://imgur.com/LH8gUtt (translated for your language)

The problem with this is, that this "feature" somehow even 
manages to catch windows fail-fast exceptions, which are supossed 
to bypass all exception handling (and debuggers!) and go directly 
to WER (Windows Error Reporting). This makes it impossible to 
debug these types of exceptions, as D nearly silently swallows 
them. My questions are now:

What exactly causes this behaviour? (e.q. which part of 
druntime/phobos/dmd/ldc2)
Is there a way to disable that?
Has anybody an other solution?
Mar 19 2018
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 19 March 2018 at 18:39:30 UTC, KytoDragon wrote:
 What exactly causes this behaviour? (e.q. which part of 
 druntime/phobos/dmd/ldc2)
Look in druntime src/rt/dmain2.d for "trapExceptions". It is set to true except "IsDebuggerPresent". That catches everything. You can't reset it to false since it makes a copy of the global var before any user code is run! And the command line switch to disable it that I'm sure I saw the PR for apparently never got in, since I can't find that code in live. So we have to hack around it.
 Is there a way to disable that?
 Has anybody an other solution?
Behold: --- import core.runtime; import std.stdio; extern(C) int _d_run_main(int argc, char** argv) { Runtime.initialize(); scope(exit) Runtime.terminate(); writeln("here"); int* n = null; *n = 1; writeln("there"); return 0; } // a dummy to trick the compiler into actually linking in the runtime void main() {} --- _d_run_main is an internal function that does a bunch of setup work. This defines our own to override the one in dmain2 and duplicates a bit of its work (though not all, there may be some things that are broken with this!) With this overridden we can get some code running without the exception catch wrapper. Works on 32 bit windows at least. Ideally, we'd just get the commandline/envvar switch to disable... and the PR stalled for ages then the author moved on https://github.com/dlang/druntime/pull/1538 we just should revive that and get it up ASAP. Much better solution than the filthy hack above.
Mar 19 2018
parent reply KytoDragon <kytodragon e.mail.de> writes:
On Monday, 19 March 2018 at 19:09:01 UTC, Adam D. Ruppe wrote:
 Look in druntime src/rt/dmain2.d for "trapExceptions". It is 
 set to true except "IsDebuggerPresent". That catches everything.

 With this overridden we can get some code running without the 
 exception catch wrapper. Works on 32 bit windows at least.


 Ideally, we'd just get the commandline/envvar switch to 
 disable... and the PR stalled for ages then the author moved on 
 https://github.com/dlang/druntime/pull/1538 we just should 
 revive that and get it up ASAP. Much better solution than the 
 filthy hack above.
I think you missunderstood my problem. I don't mean D-Exceptions, I mean Windows SEH-Exceptions. These are not caught by D's try ... catch and even your example shows the exact same behaviour. (on DMD at least, LDC complains about the redefined symbol "_d_run_main") EDIT: Ignore everything. It was my IDE that was swallowing exceptions not the compiler.
Mar 20 2018
next sibling parent KytoDragon <kytodragon e.mail.de> writes:
 EDIT: Ignore everything. It was my IDE that was swallowing 
 exceptions not the compiler.
EDIT 2: Its not my IDE, it is DUB. dub/generators/build.d, line 532: ------------ auto prg_pid = spawnProcess(exe_path_string ~ run_args); auto result = prg_pid.wait(); enforce(result == 0, "Program exited with code "~to!string(result)); ------------ and std.procedd.PID.wait only gets the exit code, ignoring anything else.
Mar 20 2018
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 20 March 2018 at 17:14:02 UTC, KytoDragon wrote:
 I think you missunderstood my problem. I don't mean 
 D-Exceptions, I mean Windows SEH-Exceptions. These are not 
 caught by D's try ... catch and even your example shows the 
 exact same behaviour.
On 32 bit, D exceptions ARE seh exceptions and try/catch works on both. But if you are on 64 bit, the implementation is different anyway...
Mar 20 2018
prev sibling parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Monday, 19 March 2018 at 18:39:30 UTC, KytoDragon wrote:
 I currently have a problem i don't know how to fix:

 Programms compiled in D (either compiler) have the annoying 
 property that they absorb all windows seh-exceptions, print the 
 error code and terminate the process.

 For example, the following programm will print "Program exited 
 with code -1073741819" and exit:

 module test.Test;

 void main() {
     *cast(int*)cast(void*)0 = 1;
 }

 But what I expected was the following:

 https://imgur.com/LH8gUtt (translated for your language)

 The problem with this is, that this "feature" somehow even 
 manages to catch windows fail-fast exceptions, which are 
 supossed to bypass all exception handling (and debuggers!) and 
 go directly to WER (Windows Error Reporting). This makes it 
 impossible to debug these types of exceptions, as D nearly 
 silently swallows them. My questions are now:

 What exactly causes this behaviour? (e.q. which part of 
 druntime/phobos/dmd/ldc2)
 Is there a way to disable that?
 Has anybody an other solution?
I'm not familiar with the neither the implementation details nor why it swallows all SEH exceptions, but anyway here's a few starting points: * most (all?) of the exception handling support code is in the druntime 'src/rt/' folder - look for files starting with 'deh', e.g. https://github.com/dlang/druntime/blob/master/src/rt/deh_win32.d for dmd -m32 (Digital Mars C runtime) and https://github.com/dlang/druntime/blob/master/src/rt/deh_win64_posix.d for the rest of the dmd platform support * additionally, LDC has a modified or completely reworked version of this: https://github.com/ldc-developers/druntime/tree/ldc/src/rt * for example, for 1.7 LDC release there was significant work in this area, which among other things added C++ exception handling support: https://github.com/ldc-developers/ldc/pull/2405/files * If you see differences between the DMD and LDC behavior, the quickest way to get an answer is to post in their forums: https://forum.dlang.org/group/ldc, or on their issue tracker: https://github.com/ldc-developers/ldc/issues
Mar 19 2018