Bug 23061 – Exceptions cannot be caught by catch statement in static build

Status
RESOLVED
Resolution
INVALID
Severity
major
Priority
P1
Component
druntime
Product
D
Version
D2
Platform
x86
OS
Linux
Creation time
2022-04-26T11:39:55Z
Last change time
2022-05-24T13:41:37Z
Assigned to
No Owner
Creator
Tomoya Tanjo

Comments

Comment #0 by ttanjo — 2022-04-26T11:39:55Z
Exceptions cannot be caught in the static linked configuration but they should be caught. In the dynamic linked configuration, they can be caught as intended. I first filed it in ldc but finally I found it is a issue in druntime. - https://github.com/ldc-developers/ldc/issues/3965 # Reproduced versions I checked this issue with the following environment with Docker container. - dmd 2.098.0-r0 in Alpine Linux 3.15 - ldc 1.28.0-r0 in Alpine Linux 3.15 - ldc 1.28.1-r0 in Alpine Linux edge # How to reproduce app.d: ```dlang void main(string[] args) { try { throw new Exception("aaa"); } catch(Exception e) { } } ``` Compile and execute it in Alpine Linux image as follows: ```console $ docker run --rm -it -v $PWD:/workdir -w /workdir alpine:3.15 sh # apk --no-cache add dmd gcc musl-dev llvm-libunwind-static # dmd -c app.d # gcc -static app.o -o app -lphobos2 -lunwind # ldd app /lib/ld-musl-x86_64.so.1: app: Not a valid dynamic program # ./app ``` # Expected behavior It can be executed without errors. # Actual behavior It fails execution with the exception message. ```console # ./app src/rt/dwarfeh.d:330: uncaught exception reached top of stack This might happen if you're missing a top level catch in your fiber or signal handler [email protected](11): aaa ---------------- ??:? <ERROR: Unable to retrieve function name> [0x0] Aborted ``` Note that it can successfully be executed when I compile it with `dmd app.d`. --- I reproduce the same issue with ldc as the following instructions: ```console $ docker run --rm -it -v $PWD:/workdir -w /workdir alpine:3.15 sh # apk --no-cache add ldc gcc musl-dev llvm-libunwind-static # ldc2 -static app.d # ./app rt/dwarfeh.d:354: uncaught exception reached top of stack This might happen if you're missing a top level catch in your fiber or signal handler [email protected](11): aaa ---------------- src/ctype/isspace.c:10 <ERROR: Unable to retrieve function name> [0x0] Aborted ```
Comment #1 by ttanjo — 2022-04-28T21:07:24Z
I changed the severity to `major` because it prevents from using exception, that is a language feature of D.
Comment #2 by ttanjo — 2022-05-22T12:56:25Z
I found that this issue only happens when dmd is built with `DRuntime_Use_Libunwind`. I built dmd with `DRuntime_Use_Libunwind` on Alpine Linux edge and obtained the following results. When `app.d` is built without `-lunwind`, it works as intended as follows: ```console $ ./dmd/generated/linux/release/64/dmd -c app.d $ cc app.o -o app -m64 -static -Xlinker --export-dynamic -L./dmd/generated/linux/release/64/../../../../../phobos/generated/linux/release/64 -Xlinker -Bstatic -lphobos2 -lpthread -lm -lrt -ldl $ ./app $ echo $? 0 ``` On the other hand, when it is built with `-lunwind`, it does not work as reported. ```console $ ./dmd/generated/linux/release/64/dmd -c app.d $ cc app.o -o app -m64 -static -Xlinker --export-dynamic -L./dmd/generated/linux/release/64/../../../../../phobos/generated/linux/release/64 -Xlinker -Bstatic -lphobos2 -lpthread -lm -lrt -ldl -lunwind $ ./app src/rt/dwarfeh.d:330: uncaught exception reached top of stack This might happen if you're missing a top level catch in your fiber or signal handler [email protected](5): aa Aborted $ echo $? 134 ```
Comment #3 by ttanjo — 2022-05-24T13:41:37Z
I close this issue because it is a matter of linker options rather than druntime itself. It only happens when using `gcc` on Alpine Linux. It does not happen when using `clang`. When we use `gcc` as a linker, it needs `-Xlinker --eh-frame-hdr`. ```console $ dmd -c app.d $ gcc app.o -o app -m64 -static -Xlinker --eh-frame-hdr -Xlinker --export-dynamic -L/usr/lib/ -Xlinker -Bstatic -lphobos2 -lpthread -lm -lrt -ldl -lunwind $ echo $? 0 ``` When we use `clang` as a linker, it works without `-Xlinker --eh-frame-hdr` because `clang` implicitly passes them to `ld`. ```console $ dmd -c app.d $ clang app.o -o app -m64 -static -Xlinker --export-dynamic -L/usr/lib/ -Xlinker -Bstatic -lphobos2 -lpthread -lm -lrt -ldl -lunwind $ ./app $ echo $? 0 ```