-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
std assumes that accessing an already-initialized TLS variable is async-signal-safe #133698
Comments
That depends on whether native TLS is supported. If it is, then TLS is provided by the combined efforts of the dynamic linker and libc (it further depends on the TLS access model, e.g. local-exec cannot actually be made async-signal unsafe). If it is not, we rely on pthread keys, those are provided by libc. |
Both. It's part of posix when using
TLS values can get destroyed and then require reinitialization if some code runs during or after thread local cleanup. So having them initialized once is not a guarantee that the allocation will not happen again.
Hrrm, maybe we could put those variables somewhere in the signal stack allocation instead, but I don't know of a async-signal-safe way to retrieve the stack base. |
Currently, the signal stack is uninstalled before destructors are run, so stack overflows will just directly crash. #131282 will change this, but it also switches the TLS variables to |
That |
If we let people change the TLS model (rust-lang/compiler-team#805), we better make sure that std is sound with all of them. |
The gnu documentation says it's only as-unsafe on hurd. |
That MCP is about TLS dialects, which are a bit different than models. Both the local-exec and initial-exec TLS models have AS-safe accesses by default, because the TLS access is performed simply by offsetting from the thread pointer. The general-dynamic and local-dynamic models are the problematic ones, independent of dialect, since they do a function call to retrieve the address, and that function is not always AS-safe (e.g. glibc lazily allocates the TLS storage, which makes the first access AS-unsafe). Here's a good summary of all this: https://maskray.me/blog/2021-02-14-all-about-thread-local-storage (it even mentions signal safety). |
That's unfortunate, but might not be deal-breaking. I just discovered this passage in the SUS (section 2.4.4):
|
Ah, I didn't realize there's two (orthogonal?) degrees of freedom here. Thanks for pointing that out. |
TLS accesses are not documented to be async-signal-safe, but they mostly are – except for the first access to a variable. We rely on that: we install signal handlers that access thread-local variables, but we ensure they have been accessed before setting up the signal handler. This would be a good thing to discuss with the runtimes we depend on, since hopefully they can provide this as an actual guarantee, or else we'll learn that we can't rely on it.
@joboet @the8472 in terms of interaction with POSIX, what exactly are we relying on here? Or are the kind of TLS variables we are using not part of POSIX? Is it a libc thing, a linker thing, or something else?
The text was updated successfully, but these errors were encountered: