Help with static build

Hi all,

I’ve been experimenting with static builds of crystal apps for binary distribution

However I’ve been struggling to make this work reliably.
I created an example application to demonstrate the issue:

you can build the application locally and run it, it works as expected:

crystal build ./src/app.cr
./app -e

however the static app errors and exits without any output

docker-compose build
docker-compose up -d
docker logs crystal-static-test-static-1

Simplifying the application, removing the spawn and channel, has the application building and running statically without issue. Alternatively, having the channel pass Nil instead of the exception also results in a functional application.

Running some of our more complicated applications statically has resulted in correct functionality for a period of time before exiting with

Failed to raise an exception: END_OF_STACK
[0x458236] ???
[0x42ce58] ???
[0x4395ae] ???
[0x433ec9] ???
[0xc75545] ???

Tried to raise:: Unknown DW_FORM_data16 (Exception)
  from usr/lib/crystal/core/crystal/dwarf/info.cr:83:29 in '??'
  from usr/lib/crystal/core/crystal/dwarf/info.cr:67:23 in '??'
  from usr/lib/crystal/core/exception/call_stack/elf.cr:10:7 in '??'
  from src/ldso/dl_iterate_phdr.c:45:1 in '??'

This might be unrelated. However I have a feeling the issues are related to calculating backtraces for exceptions that are no longer in the scope they originated in.

To extract the static executable for inspection / running on your local machine you can run
docker buildx build --platform linux/amd64 --output type=local,dest=folder .

Any ideas or help in this matter would be much appreciated

I run the binary manually, it seem like terminated with no error.

/ $ ./static 

test terminated
last error was: 

when run with -e, it seem like work as expect?

/ $ ./static -e -c 5
running exception test:
!.!.!.!.!.
test terminated
last error was: example error (Exception)
  from app/src/app.cr:52:9 in '->'
  from usr/lib/crystal/core/fiber.cr:146:11 in 'run'
  from usr/lib/crystal/core/fiber.cr:98:34 in '->'
  from ???

If you change Dockerfile like this:

@@ -90,4 +92,4 @@ USER appuser:appuser
 # Run the app binding on port 3000
 EXPOSE 3000
 ENTRYPOINT ["/static"]
-CMD ["/static", "-e"]
+CMD ["-e", "-c", "5"]

You can see same output as above.

 ╰─ $ docker-compose up
[+] Running 1/0
 ⠿ Container crystal-static-test-static-1  R...                                          0.1s
Attaching to crystal-static-test-static-1
crystal-static-test-static-1  | running exception test:
crystal-static-test-static-1  | !.!.!.!.!.
crystal-static-test-static-1  | test terminated
crystal-static-test-static-1  | last error was: example error (Exception)
crystal-static-test-static-1  |   from app/src/app.cr:52:9 in '->'
crystal-static-test-static-1  |   from usr/lib/crystal/core/fiber.cr:146:11 in 'run'
crystal-static-test-static-1  |   from usr/lib/crystal/core/fiber.cr:98:34 in '->'
crystal-static-test-static-1  |   from ???
crystal-static-test-static-1 exited with code 0

weird, seems to be working for me now too, with no change to the dockerfile… :exploding_head:

although I still have our web services crashing with Failed to raise an exception: END_OF_STACK
which seems to be an issue with parsing the elf file. Possibly related to Add support for DWARF 5 by straight-shoota · Pull Request #11399 · crystal-lang/crystal · GitHub

One thing you could do is patch the method where it raises (usr/lib/crystal/core/crystal/dwarf/info.cr:83) to, in addition to raising, writing the message to a file, maybe also write all of the Info’s instance vars. That way when it happens we’ll at least know what are the problematic values.

can do

@asterite @straight-shoota it looks like an issue with DWARF Version 5 support

Looks like it represents a 128bit integer and I assume this hasn’t been implemented yet?

created a pull request to resolve: fix(crystal/dwarf/info): parse Data16 values by stakach · Pull Request #12497 · crystal-lang/crystal · GitHub

2 Likes