-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cargo test
for an LD_PRELOAD
dylib
causes runtime error in 1.81.0
#130210
Comments
cargo test
for an LD_PRELOAD dylib causes runtime error in 1.81.0
cargo test
for an LD_PRELOAD dylib causes runtime error in 1.81.0cargo test
for an LD_PRELOAD
dylib
causes runtime error in 1.81.0
Thanks @ehuss! Yeah I was in doubt of where to put it, but since I imagined that |
Hi! From that linked thread that I opened we have had a bit of discussion. Just so I have it clear and see if it makes sense to have this bug report open or not:
Given the above is true about the
This is the same doubt written in the Solutions section above: is a way to test code linked to
The answer by u/CAD97 to the above question is probably. Aside from the testing suggested, should I fear any other conflicts of this kind? Does the output type |
This falls in the "use before and after |
I can confirm this when trying to running a test binary compiled to WebAssembly, where I've overridden the methods for getting environment variables. I had some println! calls in there, which started failing in 1.81.0. Removing the println calls makes the test pass again. |
Fixes rust-lang#130210. Since rust-lang#124881, `ReentrantLock` uses `ThreadId` to identify threads. This has the unfortunate consequence of breaking uses of `Stdout` before main: Locking the `ReentrantLock` that synchronizes the output will initialize the thread ID before the handle for the main thread is set in `rt::init`. But since that would overwrite the current thread ID, `thread::set_current` triggers an abort. This PR fixes the problem by using the already initialized thread ID for constructing the main thread handle and allowing `set_current` calls that do not change the thread's ID.
std: fix stdout-before-main Fixes rust-lang#130210. Since rust-lang#124881, `ReentrantLock` uses `ThreadId` to identify threads. This has the unfortunate consequence of breaking uses of `Stdout` before main: Locking the `ReentrantLock` that synchronizes the output will initialize the thread ID before the handle for the main thread is set in `rt::init`. But since that would overwrite the current thread ID, `thread::set_current` triggers an abort. This PR fixes the problem by using the already initialized thread ID for constructing the main thread handle and allowing `set_current` calls that do not change the thread's ID.
std: fix stdout-before-main Fixes rust-lang#130210. Since rust-lang#124881, `ReentrantLock` uses `ThreadId` to identify threads. This has the unfortunate consequence of breaking uses of `Stdout` before main: Locking the `ReentrantLock` that synchronizes the output will initialize the thread ID before the handle for the main thread is set in `rt::init`. But since that would overwrite the current thread ID, `thread::set_current` triggers an abort. This PR fixes the problem by using the already initialized thread ID for constructing the main thread handle and allowing `set_current` calls that do not change the thread's ID.
Rollup merge of rust-lang#131233 - joboet:stdout-before-main, r=tgross35 std: fix stdout-before-main Fixes rust-lang#130210. Since rust-lang#124881, `ReentrantLock` uses `ThreadId` to identify threads. This has the unfortunate consequence of breaking uses of `Stdout` before main: Locking the `ReentrantLock` that synchronizes the output will initialize the thread ID before the handle for the main thread is set in `rt::init`. But since that would overwrite the current thread ID, `thread::set_current` triggers an abort. This PR fixes the problem by using the already initialized thread ID for constructing the main thread handle and allowing `set_current` calls that do not change the thread's ID.
Problem
Hi! I have a project where I define a
dylib
to use asLD_PRELOAD
by linking anextern "C"
function to.init_array
. I was using Rust 1.80.1 and unit tests were working without issues.However, since bumping to 1.81.0, our CI (Linux runners) started failing though no significant changes had been added to the code. The thing is, if you built the project with either version and passed the resulting
.so
asLD_PRELOAD
it seemed to work without issues.I have set up a minimal reproducer that you can inspect here. It is just a "hello world"
lib.rs
with a simple unit and integration test, though these tests can be removed and the output will be the same when running the steps below. The reproducer'sREADME.md
includes sample commands ran throughdocker
, as I wrote it from a different OS.Steps
src/lib.rs
.cargo test
with Rust 1.80.1. Should work.cargo test
with Rust 1.81.0. Should fail withfatal runtime error: thread::set_current should only be called once per thread
.cargo build
and call some command passing the resulting.so
asLD_PRELOAD
, such asLD_PRELOAD=target/debug/libpreload_tests.so ls -lah
. Should work for Rust 1.80.1.cargo build
and call some command passing the resulting.so
asLD_PRELOAD
, such asLD_PRELOAD=target/debug/libpreload_tests.so ls -lah
. Should work for Rust 1.81.0.Possible Solution(s)
I have noticed that if I add
#[cfg(not(test))]
to thestatic
that stores theextern "C"
function and is linked to.init_array
the tests run without issues in both versions, but I'm not sure if this is a proper solution and the way to work with testingLD_PRELOAD
dylib
s or if I'm masking some other problem.Notes
I have opened the issue here because I think the failure might lie in how the "test runner executable" is built and ran. If you read the outputs I pasted on the reproducer's
README.md
for thecargo test
runs, you'll see that the behavior linked to.init_array
is present in the test runner as the log line"HOLA FROM LD_PRELOAD!"
is shown at the beginning, in both Rust toolchain versions.Please let me know if this is not the proper place and point me to the appropriate one to open the report.
While I am not very knowledgeable about the internals that might have caused this, I'd like to figure this out, particularly to make sure that this cannot happen on an eventual "production" usage with the compiled project and not only on tests, given the actual problem I'm working with would require performing more than just a
println!
and any crash during the preload prevents the actual process from running (placing it in/etc/ld.so.preload
could seemingly brick a host!).I get that this kind of lower level, run-before-main behaviors can be pretty hard to do well, so I really want to be sure I'm doing things right.
Version
The text was updated successfully, but these errors were encountered: