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
```