-
Notifications
You must be signed in to change notification settings - Fork 24
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
Move fork
from origin to c_scape
#84
Conversation
Making fork safe would make calling |
Should it be the responsibility of
Can you say more about what the hazard is here? If the sqlite bindings expose a safe API, we should be able to make the same assumptions we do about Rust code. Or does it use |
Normally sqlite locks the database file. A fork can happen after the database was locked, in which case we now got two competing sqlite instances fighting for the same database. The resulting corruption itself could lead to UB inside the sqlite code, or a TOCTOU could happen between checking that the file contents are sane and actually using it. (for example because the compiler assumes that the memory doesn't change behind the back of the current thread due to data races being UB) Sqlite supports using |
origin::program::fork
as safe.origin::program::fork
less unsafe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new doc comment LGTM. Didn't closely review the rest of the PR.
I think in theory there are ways these safety concerns could be pushed to other places. But ultimately, |
Thinking about this more, I've now written bytecodealliance/rustix#137 to organize my thoughts, and point to a new overall direction here. |
origin::program::fork
less unsafefork
from origin to c_scape
b17b573
to
58850ac
Compare
32-bit arm is failing because parking_lot's Mutex uses |
0c4235c
to
0a85137
Compare
I think the thing to do for now is to temporarily disable 32-bit arm support. I expect the available options with parking_lot will evolve over time, and we can re-evaluate 32-bit arm support when we have other options. |
Move `fork` from origin to c-scape, and convert it back to using `unsafe extern "C" fn()` hooks instead of safe boxed closures. See bytecodealliance/rustix#137 for discussion. Add an at_thread_exit_raw to origin, which allows thread destructors to be registered without allocating, which is important since Rust will register TLS destructors while threads are being constructed, before parking_lot is prepared for the global allocator to take locks. Update to the latest rustix, and the change from a safe execve to an unsafe raw execveat. This similarly allows it to avoid allocating, which is important as it's primarily called in the child of `fork`. And switch to a branch of parking_lot with changes to allow parking_lot locks to be used from within global allocator implementations. These changes allow us to move the `#[global_allocator]` back to the mustang crate, and restore the wee_alloc allocator option. More generally, origin and c-scape should in theory now work with any global allocator implementation.
This avoids the problem that `execveat` isn't always supported.
For better global-alloc compatibility, allocate main-thread data with mmap_anonymous instead of with alloc.
32-bit arm is failing because parking_lot's `Mutex` uses `std::time::Instant::now` to implement fairness, which takes a lock on 32-bit arm to ensure monotonicity because it doesn't have 64-bit atomics and can't guarantee that `CLOCK_MONOTONIC` is actually monotonic, so it then deadlocks on the bucket lock.
Use `#[cfg_attr(..., path = "...")]` to conditionally define modules, which simplifies the lib.rs file. And clean up several comments.
has-elf-tls was renamed to has-thread-local. Define both for now, so that we work with versions of Rust before and after the rename.
To support both old and new Rust compilers, we need both has-elf-tls and has-thread-local in the target json files for now. Disable the stderr comparison checks which get caught on the warning that one of them is unsupported.
f060927
to
2ab885a
Compare
After a fork, the child only has one thread, and it looks like all the
other threads are suspended. This may leave behind locks in locked
states and cause deadlocks, however deadlocks are not considered unsafe.
Consequently, fork doesn't need to be unsafe.
This also changes the
on_fork
callback functions to beBox<Fn() + Send>
so that it's safe to call them, and adds code toc-scape and non-mustang targets to wrap them as needed.