Skip to content

Use libc::sigaction() instead of sys::signal() to prevent a deadlock - #88828

Merged
bors merged 3 commits into
rust-lang:masterfrom
FabianWolff:issue-88585
Oct 6, 2021
Merged

Use libc::sigaction() instead of sys::signal() to prevent a deadlock#88828
bors merged 3 commits into
rust-lang:masterfrom
FabianWolff:issue-88585

Conversation

@FabianWolff

@FabianWolffFabianWolff commented Sep 10, 2021

Copy link
Copy Markdown
Contributor

Fixes#88585. POSIX specifies that after forking,

to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.

Rust's standard library does not currently adhere to this, as evidenced by #88585. The child process calls sys::signal(), which on Android calls libc::dlsym(), which is not async-signal-safe, and in fact causes a deadlock in the example in #88585.

I think the easiest solution here would be to just call libc::sigaction() instead, which is async-signal-safe, provides the functionality we need, and is apparently available on all Android versions because it is also used e.g. here.

@rust-highfive

Copy link
Copy Markdown
Contributor

r? @dtolnay

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfiverust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 10, 2021
@rust-log-analyzer

This comment has been minimized.

@v-lebedev

Copy link
Copy Markdown

I've tested the fix on Android Emulator x86-64 (Android 10), and on real devices (Android from 6.0.1 to 11). It works!

Locking g_dl_mutex...
Spawning ps...
ps spawned!
USER PID PPID VSZ RSS WCHAN ADDR S NAME
shell 5002 25748 10790496 2692 futex_wait_queue_me 0 S linker-deadlock
shell 5005 5002 10774564 3368 0 0 R ps
dlsym'ing done
Done

@FabianWolff

Copy link
Copy Markdown
ContributorAuthor

I've tested the fix on Android Emulator x86-64 (Android 10), and on real devices (Android from 6.0.1 to 11). It works!

Happy to hear that! And thanks a lot for testing this @d3fl4t3!

@dtolnaydtolnay left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This looks good.

Comment threadlibrary/std/src/sys/unix/process/process_unix.rs Outdated
The reference automatically coerces to a pointer. Writing an explicit
cast here is slightly misleading because that's most commonly used when
a pointer needs to be converted from one pointer type to another, e.g.
`*const c_void` to `*const sigaction` or vice versa.
@dtolnay

Copy link
Copy Markdown
Member

@bors r+

@bors

bors commented Sep 29, 2021

Copy link
Copy Markdown
Collaborator

📌 Commit e3e5ae9 has been approved by dtolnay

@borsbors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 29, 2021
Manishearth added a commit to Manishearth/rust that referenced this pull request Sep 30, 2021
Use `libc::sigaction()` instead of `sys::signal()` to prevent a deadlock
Fixesrust-lang#88585. POSIX [specifies](https://man7.org/linux/man-pages/man3/fork.3p.html) that after forking,
> to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.
Rust's standard library does not currently adhere to this, as evidenced by rust-lang#88585. The child process calls [`sys::signal()`](https://github.com/rust-lang/rust/blob/7bf0736e130e2203c58654f7353dbf9575e49d5c/library/std/src/sys/unix/android.rs#L76), which on Android calls [`libc::dlsym()`](https://github.com/rust-lang/rust/blob/7bf0736e130e2203c58654f7353dbf9575e49d5c/library/std/src/sys/unix/weak.rs#L101), which is [**not**](https://man7.org/linux/man-pages/man7/signal-safety.7.html) async-signal-safe, and in fact causes a deadlock in the example in rust-lang#88585.
I think the easiest solution here would be to just call `libc::sigaction()` instead, which [is](https://man7.org/linux/man-pages/man7/signal-safety.7.html) async-signal-safe, provides the functionality we need, and is apparently available on all Android versions because it is also used e.g. [here](https://github.com/rust-lang/rust/blob/7bf0736e130e2203c58654f7353dbf9575e49d5c/library/std/src/sys/unix/stack_overflow.rs#L112-L114).
@Manishearth

Copy link
Copy Markdown
Member

@bors r-

#89402 (comment)

warning: dropping unsupported crate type `dylib` for target `x86_64-unknown-redox`
error[E0609]: no field `sa_sigaction` on type `sigaction`
|
|
337 | action.sa_sigaction = libc::SIG_DFL;
|
|
= note: available fields are: `sa_handler`, `sa_flags`, `sa_restorer`, `sa_mask`
For more information about this error, try `rustc --explain E0609`.
[RUSTC-TIMING] std test:false 2.497
warning: `std` (lib) generated 1 warning

@borsbors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Sep 30, 2021
@FabianWolff

Copy link
Copy Markdown
ContributorAuthor

So neither .sa_sigaction nor .sa_handler are universally available, and there doesn't seem to be an easy way to detect which platform uses which field name. I have therefore restricted my original fix to just Android for now (which is the platform that #88585 was discovered on).

@rustbot ready

@rustbotrustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 1, 2021
@dtolnay

Copy link
Copy Markdown
Member

@bors r+

@bors

bors commented Oct 3, 2021

Copy link
Copy Markdown
Collaborator

📌 Commit 65ef265 has been approved by dtolnay

@borsbors removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 3, 2021
@borsbors added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Oct 3, 2021
Manishearth added a commit to Manishearth/rust that referenced this pull request Oct 5, 2021
Use `libc::sigaction()` instead of `sys::signal()` to prevent a deadlock
Fixesrust-lang#88585. POSIX [specifies](https://man7.org/linux/man-pages/man3/fork.3p.html) that after forking,
> to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.
Rust's standard library does not currently adhere to this, as evidenced by rust-lang#88585. The child process calls [`sys::signal()`](https://github.com/rust-lang/rust/blob/7bf0736e130e2203c58654f7353dbf9575e49d5c/library/std/src/sys/unix/android.rs#L76), which on Android calls [`libc::dlsym()`](https://github.com/rust-lang/rust/blob/7bf0736e130e2203c58654f7353dbf9575e49d5c/library/std/src/sys/unix/weak.rs#L101), which is [**not**](https://man7.org/linux/man-pages/man7/signal-safety.7.html) async-signal-safe, and in fact causes a deadlock in the example in rust-lang#88585.
I think the easiest solution here would be to just call `libc::sigaction()` instead, which [is](https://man7.org/linux/man-pages/man7/signal-safety.7.html) async-signal-safe, provides the functionality we need, and is apparently available on all Android versions because it is also used e.g. [here](https://github.com/rust-lang/rust/blob/7bf0736e130e2203c58654f7353dbf9575e49d5c/library/std/src/sys/unix/stack_overflow.rs#L112-L114).
@ManishearthManishearth mentioned this pull request Oct 5, 2021
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 5, 2021
…arth
Rollup of 10 pull requests
Successful merges:
- rust-lang#88706 (Normalize associated type projections when checking return type of main)
- rust-lang#88828 (Use `libc::sigaction()` instead of `sys::signal()` to prevent a deadlock)
- rust-lang#88871 (Fix suggestion for nested struct patterns)
- rust-lang#89317 (Move generic error message to separate branches)
- rust-lang#89351 (for signed wrapping remainder, do not compare lhs with MIN)
- rust-lang#89442 (Add check for duplicated doc aliases)
- rust-lang#89502 (Fix Lower/UpperExp formatting for integers and precision zero)
- rust-lang#89523 (Make `proc_macro_derive_resolution_fallback` a future-breakage lint)
- rust-lang#89532 (Document behavior of `MaybeLiveLocals` regarding enums and field-senstivity)
- rust-lang#89546 (Make an initial guess for metadata size to reduce buffer resizes)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
@bors
bors merged commit eb86098 into rust-lang:masterOct 6, 2021
@rustbotrustbot added this to the 1.57.0 milestone Oct 6, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

deadlock: Command::spawn is trying to dlsym after fork, but linker mutex is locked

8 participants

@FabianWolff@rust-highfive@rust-log-analyzer@v-lebedev@dtolnay@bors@Manishearth@rustbot