removed sentry-sdk patch
treefmt / nix fmt (pull_request) Successful in 4s
build_systems / prebuild-common-x86-64-v3 (pull_request) Successful in 21s
build_systems / build-portal-1 (pull_request) Successful in 17s
build_systems / build-brain (pull_request) Successful in 43s
build_systems / build-bob (pull_request) Successful in 43s
test ebook search / test-ebook-search (pull_request) Successful in 1m8s
build_systems / build-rhapsody-in-green (pull_request) Successful in 55s
build_systems / build-jeeves (pull_request) Successful in 1m6s
treefmt / nix fmt (pull_request) Successful in 4s
build_systems / prebuild-common-x86-64-v3 (pull_request) Successful in 21s
build_systems / build-portal-1 (pull_request) Successful in 17s
build_systems / build-brain (pull_request) Successful in 43s
build_systems / build-bob (pull_request) Successful in 43s
test ebook search / test-ebook-search (pull_request) Successful in 1m8s
build_systems / build-rhapsody-in-green (pull_request) Successful in 55s
build_systems / build-jeeves (pull_request) Successful in 1m6s
it was only required for rhapsody-in-green
This commit is contained in:
@@ -8,7 +8,7 @@ _final: prev:
|
|||||||
(_pythonFinal: pythonPrev: {
|
(_pythonFinal: pythonPrev: {
|
||||||
pytest-xdist = import ./pytest-xdist { inherit (pythonPrev) pytest-xdist; };
|
pytest-xdist = import ./pytest-xdist { inherit (pythonPrev) pytest-xdist; };
|
||||||
scipy = import ./scipy { inherit (pythonPrev) scipy; };
|
scipy = import ./scipy { inherit (pythonPrev) scipy; };
|
||||||
sentry-sdk = import ./sentry-sdk { inherit (pythonPrev) sentry-sdk; };
|
# sentry-sdk = import ./sentry-sdk { inherit (pythonPrev) sentry-sdk; };
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
# Sentry SDK thread-metadata test isolation
|
|
||||||
|
|
||||||
The fallback tests globally mock `threading.current_thread` while a worker
|
|
||||||
is running. Python 3.14's `Thread.join()` also calls that function. A one-use
|
|
||||||
mock can therefore be consumed by the wrong caller or raise `StopIteration`
|
|
||||||
when the main thread joins the worker.
|
|
||||||
|
|
||||||
## Scope and behavior
|
|
||||||
|
|
||||||
`isolate-threading-mocks.patch` changes three neighboring thread-metadata
|
|
||||||
tests in `tests/test_utils.py`, including the formerly excluded
|
|
||||||
`test_get_current_thread_meta_main_thread`.
|
|
||||||
|
|
||||||
Each test replaces only `sentry_sdk.utils.threading`, wraps the real module
|
|
||||||
for unmocked operations, and sets the SDK lookup's return value. The real
|
|
||||||
`Thread.join()` continues using Python's unmodified `threading` module.
|
|
||||||
The fallback-result assertions remain; SDK production code is unchanged.
|
|
||||||
|
|
||||||
## Reproduction and focused checks
|
|
||||||
|
|
||||||
Use a disposable Sentry SDK 2.66.0 checkout and its Python test dependencies.
|
|
||||||
From this directory:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
patch --fuzz=0 -d /path/to/sentry-python -p1 < isolate-threading-mocks.patch
|
|
||||||
cd /path/to/sentry-python
|
|
||||||
python -m pytest tests/test_utils.py -k get_current_thread_meta -q
|
|
||||||
```
|
|
||||||
|
|
||||||
To reproduce the race, hold the worker inside its mock just after
|
|
||||||
`get_current_thread_meta()` returns, signal that point to the main thread,
|
|
||||||
and call `Thread.join()` before releasing the worker. Use an independent
|
|
||||||
bounded release so the patched join can finish. The original test raises
|
|
||||||
`StopIteration` in `join`; the patched test passes under the same schedule.
|
|
||||||
Perform this scheduling instrumentation only in a disposable checkout.
|
|
||||||
|
|
||||||
## Upstream status
|
|
||||||
|
|
||||||
This is a standalone test patch for Sentry SDK 2.66.0. No upstream submission
|
|
||||||
was made during this work. Recheck mock isolation and Python threading
|
|
||||||
behavior when upgrading the SDK or interpreter.
|
|
||||||
|
|
||||||
## Local NixOS integration and build results
|
|
||||||
|
|
||||||
[`../default.nix`](../default.nix) loads `default.nix` through
|
|
||||||
`pythonPackagesExtensions`. From the repository root:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
nix build --no-link -L .#nixosConfigurations.jeeves.pkgs.python314Packages.sentry-sdk
|
|
||||||
```
|
|
||||||
|
|
||||||
The patched package passed 2,356 tests with 116 existing skips on Python
|
|
||||||
3.14.7. The controlled join reproduction failed before the fix and passed
|
|
||||||
after it.
|
|
||||||
|
|
||||||
That package build used the preceding dependency set with this patch to avoid
|
|
||||||
unrelated rebuilds after pytest-xdist changed. The integrated host derivation
|
|
||||||
was evaluated; a complete NixOS rebuild was not performed.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{ sentry-sdk }:
|
|
||||||
sentry-sdk.overridePythonAttrs (old: {
|
|
||||||
patches = (old.patches or [ ]) ++ [ ./isolate-threading-mocks.patch ];
|
|
||||||
})
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
Subject: [PATCH] tests: isolate SDK thread lookup mocks from Python threading
|
|
||||||
|
|
||||||
Thread.join also calls threading.current_thread on Python 3.14. A global
|
|
||||||
single-use side effect can be consumed by join instead of the SDK, or
|
|
||||||
raise StopIteration in join after the SDK consumes it. Patch the SDK's
|
|
||||||
module binding and delegate unmocked operations to the real module.
|
|
||||||
Apply the same isolation to the adjacent invalid-thread fallback tests.
|
|
||||||
|
|
||||||
--- a/tests/test_utils.py
|
|
||||||
+++ b/tests/test_utils.py
|
|
||||||
@@ -914,7 +914,8 @@
|
|
||||||
results = Queue(maxsize=1)
|
|
||||||
|
|
||||||
def target():
|
|
||||||
- with mock.patch("threading.current_thread", side_effect=["fake thread"]):
|
|
||||||
+ with mock.patch("sentry_sdk.utils.threading", wraps=threading) as sdk_threading:
|
|
||||||
+ sdk_threading.current_thread.return_value = "fake thread"
|
|
||||||
results.put(get_current_thread_meta())
|
|
||||||
|
|
||||||
thread = threading.Thread(target=target)
|
|
||||||
@@ -930,7 +931,9 @@
|
|
||||||
|
|
||||||
def target():
|
|
||||||
# mock that somehow the current thread doesn't exist
|
|
||||||
- with mock.patch("threading.current_thread", side_effect=[None]):
|
|
||||||
+ # Keep the real threading module intact for concurrent Thread.join calls.
|
|
||||||
+ with mock.patch("sentry_sdk.utils.threading", wraps=threading) as sdk_threading:
|
|
||||||
+ sdk_threading.current_thread.return_value = None
|
|
||||||
results.put(get_current_thread_meta())
|
|
||||||
|
|
||||||
main_thread = threading.main_thread()
|
|
||||||
@@ -945,7 +948,8 @@
|
|
||||||
results = Queue(maxsize=1)
|
|
||||||
|
|
||||||
def target():
|
|
||||||
- with mock.patch("threading.current_thread", return_value="fake thread"):
|
|
||||||
+ with mock.patch("sentry_sdk.utils.threading", wraps=threading) as sdk_threading:
|
|
||||||
+ sdk_threading.current_thread.return_value = "fake thread"
|
|
||||||
results.put(get_current_thread_meta())
|
|
||||||
|
|
||||||
main_thread = threading.main_thread()
|
|
||||||
Reference in New Issue
Block a user