Closed j-m-harris closed 1 month ago
If linking a different build of libssl doesn't reproduce the issue, that indicates a problem with the library. For the Crystal bindings it's irrelevant whether libssl is linked statically or dynamically. Codegen is identical in both cases. To further investigate this hypothesis, I'd suggest to try different builds of OpenSSL. Maybe build it locally to ensure compatibility with the host CPU.
@straight-shoota thanks for the response.
I agree the libs have the potential to be different when static linking is used:
I'll investigate precisely which versions are being used in each scenario.
If you build and run in the 84codes/crystal image, both static and dynamic versions of the library are the ones available in that image. But static and dynamic versions have some differences and these could be relevant.
Pretty sure they aren't the same, as the dockerfile has multiple sources: https://github.com/cloudamqp/amqproxy/blob/main/Dockerfile#L8
We don't need to discuss how amqproxy structures their build in this project though, out of scope.
This actually provides a quite relevant bit of information.
The app is built on 84codes/crystal:1.13.2-alpine
linking against the libssl.so.3
included in that image.
But then the binary is copied to a different image based on alpine:latest
. So when you execute it, it uses libssl.so.3
from that image. And that could be a different library version than the one from the build image.
Apart from binary compatibility issues, if the libssl version at load time is different from compile time, the Crystal bindings' expectations about library features is incorrect.
Generally, the loader should error if it detects that the runtime library is incompatible with the linked one. But this might not be 100% accurate. It's generally best to use the same library version in the builder and the runner.
Static linking trivially ensures this, of course.
Agreed. I'll see whether using dynamic linking with libraries copied from the builder image is also stable at runtime.
Using dynamic linking with the libraries from the builder image does appear to be stable, so we'll raise an issue with amqproxy for their build approach.
if the libssl version at load time is different from compile time, the Crystal bindings' expectations about library features is incorrect.
@straight-shoota Thanks for confirming this, and taking a look.
Bug Report
We've been experiencing a problem with amqproxy which was originally submitted as https://github.com/cloudamqp/amqproxy/issues/174
However I suspect the problem could lie in crystal itself.
Upon negotiating the connection to the upstream server, amqproxy stops with illegal instruction.
84codes/crystal:1.13.2-alpine
The backtrace is:
Afaik crystal uses LLVM, whose trap intrinsic will generate a ud2 instruction. That could mean that SIGILL is a red herring for an invalid memory access. Or am I barking up the wrong tree completely?
The default approach is to use libssl as a shared object, but interestingly we have been unable to reproduce if
shards build --static
is used instead.