Repository navigation
pthread_exit crashes on threads created by std::thread::spawn in 1.84, not 1.83, breaking pyo3-log #135929
Description
Activity
- addedneeds-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triagingThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
on Jan 23, 2025 - addedT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
on Jan 23, 2025 - addedA-threadArea: `std::thread`Area: `std::thread`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.and removedT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
on Jan 23, 2025 Relevant discussions: rust-lang/unsafe-code-guidelines#404
Even if it's bad, I believe we need to have a working way to write Python libraries in Rust, even if the libraries spawn Rust threads that can potentially call into Python.
debuginfo = 0is a working way, but it feels too ugly.The other argument is that Rust 1.84 has the MSRV-aware resolver, so e.g. reverting the change just for 1.84, leaving people stuck in Rust 1.84, is much better than leaving them stuck in 1.83.
I believe it would be possible to make pyo3-log marshal everything to a Python thread, but that would not work if there are non-pyo3-log causes of the problem.
cc @vorner for the pyo3-log problem
- addedE-needs-bisectionCall for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustcCall for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustcS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueStatus: A Minimal Complete and Verifiable Example has been found for this issueand removedneeds-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triagingThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
on Jan 23, 2025 9 remaining items
- added 2 commits that reference this issue
on Jan 26, 2025 @davidhewitt what do you think of PyO3/pyo3#4874 ?
Thanks, I've seen you've pushed that, I'm very short of time at the moment so please allow me a few days to find a moment to sit down and review fully.
Cool.
- added 2 commits that reference this issue
on Jan 29, 2025 - added a commit that references this issue
on Feb 13, 2025 - added a commit that references this issue
on Feb 19, 2025 - added a commit that references this issue
on Mar 9, 2025 - added a commit that references this issue
on Mar 9, 2025 We handled a fix in PyO3 side for this, should we close this issue?
Yea, closing
- added a commit that references this issue
on Oct 3, 2026
Meta
Tested on Ubuntu 24.04 and Amazon Linux 2, x86_64.
Workaround to the production problem
In your Cargo.toml that is compiling your Python module, set
This prevents the 1.84 crashes.
However, there is still UB going on even with this setting.
The Production Problem
The crate pyo3-log installs a bridge that makes log functions call into Python. This means that all calls to
logging::info!etc will take the GIL.Python has a stage during interpreter shutdown where attempts to take the GIL will cause a
pthread_exit. Python 3.14 (still Alpha today, targeted to be released by the end of this year) will change this in python/cpython#87135 - but that will take some time to reach people.This means that if you have a Python program that uses a Rust library and pyo3-log, that spawning a Rust thread, that is calling
logging::info!in a way unsynchronized with interpreter exit, you'll have unpredicatable crashes in 1.84.Minified Program
This program:
when compiled with the following options
crashes with this confusing error
This crash happens:
When using
-C panic=unwindinstead, on all versions of the compiler, you get this error:I seen the claim in Zulip (https://rust-lang.zulipchat.com/#narrow/channel/122651-general/topic/pthread_exit.20from.20a.20Rust-spawned.20thread) that this is undefined behavior, but I'll rather not break pyo3-log