Thread overview
ldc2 exception handling on macOS
Jun 02
Sergey
Jun 02
Sergey
Jun 02
Sergey
June 02

I am working on a reasonable large Dlang program that links to C and Fortran libraries. With recent updates on macOS, I was having trouble linking to the Fortran libraries but found the -L-no_compact_unwind allowed me to get a build going, so long as I also had the optimisation flag -O set. If I omitted the optimisation flag, the program would no longer catch exceptions.

I have made a small example of this behaviour below. The transcript shows first the program built with optimisation on and catching the exception. The second part shows the build without optimisation failing to catch the exception.

Am I just using the compiler incorrectly or is there a bug?

peterj@mini test-exception % ./run_test_exception.sh
Compile code
Run without throwing an exception
Success: mf=1
mf=1
Run and cause the throwing of an exception that should be caught
Caught expection message: oops
mf=2
peterj@mini test-exception % nvim run_test_exception.sh
peterj@mini test-exception % ./run_test_exception.sh
Compile code
Run without throwing an exception
Success: mf=1
mf=1
Run and cause the throwing of an exception that should be caught
rt/dwarfeh.d:369: uncaught exception reached top of stack
This might happen if you're missing a top level catch in your fiber or signal handler
test_exception.MyException@test_exception.d(17): oops
----------------
??:? object.Throwable.TraceInfo core.runtime.defaultTraceHandler(void*) [0x1047e2283]
??:? _Dmain [0x10478507b]
./run_test_exception.sh: line 9:  1155 Abort trap: 6           ./test_exception fail
peterj@mini test-exception %
# run_test_exception.sh
echo "Compile code"
# ldc2 -O -L-no_compact_unwind test_exception.d
ldc2 -L-no_compact_unwind test_exception.d
# ldc2 test_exception.d
echo "Run without throwing an exception"
./test_exception ok
echo "Run and cause the throwing of an exception that should be caught"
./test_exception fail
// test_exception.d

import std.stdio;

class MyException : Exception {
    @nogc
    this(string message, string file=__FILE__, size_t line=__LINE__,
         Throwable next=null)
    {
        super(message, file, line, next);
    }
}

string get_stuff(string incoming) {
    string outgoing = "stuff";
    if (incoming == "fail") {
        throw new MyException("oops");
    }
    return outgoing;
}

int main(string[] args)
{
    double mf = 0.0;
    try {
        mf = 1.0;
        string txt = get_stuff(args[1]);
        writefln("Success: mf=%g", mf);
    } catch (MyException e) {
        writefln("Caught expection message: %s", e.msg);
        mf = 2.0;
    }
    writefln("mf=%g", mf);
    return 0;
}
peterj@mini test-exception % ldc2 --version
LDC - the LLVM D compiler (1.38.0):
  based on DMD v2.108.1 and LLVM 18.1.5
  built with LDC - the LLVM D compiler (1.38.0)
  Default target: arm64-apple-darwin23.5.0
  Host CPU: apple-m1
  http://dlang.org - http://wiki.dlang.org/LDC
June 02

On Sunday, 2 June 2024 at 07:08:23 UTC, Peter Jacobs wrote:

>

I am working on a reasonable large Dlang program that links to C and Fortran libraries.

Sounds interesting. In which area is your project? Scientific computations?

>

Am I just using the compiler incorrectly or is there a bug?

I will try to bring attention of LDC devs to the question, but maybe next time it will better to ask such questions in LDC channel.
I have no idea what's going on there, just can confirm the behavior on my M1 Pro is the same with LDC 1.38

I've tinkered with the code a bit and found the workaround (even don't know why is it working):
if you add pragma(inline, true): before string get_stuff(string incoming) it is catching exception even without -O..

June 02

On Sunday, 2 June 2024 at 08:26:24 UTC, Sergey wrote:

>

On Sunday, 2 June 2024 at 07:08:23 UTC, Peter Jacobs wrote:

>

I am working on a reasonable large Dlang program that links to C and Fortran libraries.

Sounds interesting. In which area is your project? Scientific computations?

Ooh its about Eilmer (gdtk). Cool

June 02

On Sunday, 2 June 2024 at 08:52:13 UTC, Sergey wrote:

>

On Sunday, 2 June 2024 at 08:26:24 UTC, Sergey wrote:

>

On Sunday, 2 June 2024 at 07:08:23 UTC, Peter Jacobs wrote:

>

I am working on a reasonable large Dlang program that links to C and Fortran libraries.

Sounds interesting. In which area is your project? Scientific computations?

Ooh its about Eilmer (gdtk). Cool

Yes, that is the main code. It has been good fun and Dlang has been good to us. These days some of the postdocs run calculations on thousands of cores simultaneously so we get good value from the easy binding with C libraries such as MPI.

Thanks for the suggested workaround. When I was trying to build a small example, it was not until I put the throw inside the get_stuff function that I could trigger the odd behaviour. Maybe that could be a clue to someone who knows the insides of ldc2.

Cheers,
Peter J.

June 02

On Sunday, 2 June 2024 at 10:02:23 UTC, Peter Jacobs wrote:

>

On Sunday, 2 June 2024 at 08:52:13 UTC, Sergey wrote:

>

On Sunday, 2 June 2024 at 08:26:24 UTC, Sergey wrote:
Maybe that could be a clue to someone who knows the insides of ldc2.

Jacob mentioned this issue: https://github.com/ldc-developers/ldc/issues/4588