Skip to content

Commit a50b651

Browse files
bluetechuntitaker
authored andcommitted
Fix detection of gevent threading.local monkey-patch (#447)
* Fix detection of gevent threading.local monkey-patch The `_` in `_threading` seems like a mistake and always returns False. Removing it leads to the detection working properly: ```py Python 3.7.4 (default, Jul 16 2019, 07:12:58) [GCC 9.1.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import gevent.monkey >>> gevent.monkey.is_object_patched('_threading', 'local') False >>> gevent.monkey.is_object_patched('threading', 'local') False >>> gevent.monkey.patch_all() True >>> gevent.monkey.is_object_patched('_threading', 'local') False >>> gevent.monkey.is_object_patched('threading', 'local') True ``` * fix: Add tests
1 parent dc0dbf7 commit a50b651

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

sentry_sdk/utils.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ def _is_threading_local_monkey_patched():
759759
try:
760760
from gevent.monkey import is_object_patched # type: ignore
761761

762-
if is_object_patched("_threading", "local"):
762+
if is_object_patched("threading", "local"):
763763
return True
764764
except ImportError:
765765
pass
@@ -775,10 +775,6 @@ def _is_threading_local_monkey_patched():
775775
return False
776776

777777

778-
IS_THREADING_LOCAL_MONKEY_PATCHED = _is_threading_local_monkey_patched()
779-
del _is_threading_local_monkey_patched
780-
781-
782778
def _get_contextvars():
783779
# () -> (bool, Type)
784780
"""
@@ -788,7 +784,7 @@ def _get_contextvars():
788784
789785
https://github.com/gevent/gevent/issues/1407
790786
"""
791-
if not IS_THREADING_LOCAL_MONKEY_PATCHED:
787+
if not _is_threading_local_monkey_patched():
792788
try:
793789
from contextvars import ContextVar # type: ignore
794790

@@ -818,7 +814,6 @@ def set(self, value):
818814

819815

820816
HAS_REAL_CONTEXTVARS, ContextVar = _get_contextvars()
821-
del _get_contextvars
822817

823818

824819
def transaction_from_function(func):

test-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ tox==3.7.0
55
Werkzeug==0.14.1
66
pytest-localserver==0.4.1
77
pytest-cov==2.6.0
8+
gevent

tests/utils/test_contextvars.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import pytest
2+
import random
3+
import time
4+
5+
import gevent
6+
7+
8+
from sentry_sdk.utils import _is_threading_local_monkey_patched
9+
10+
11+
def test_gevent_is_patched():
12+
gevent.monkey.patch_all()
13+
assert _is_threading_local_monkey_patched()
14+
15+
16+
def test_gevent_is_not_patched():
17+
assert not _is_threading_local_monkey_patched()
18+
19+
20+
@pytest.mark.parametrize("with_gevent", [True, False])
21+
def test_leaks(with_gevent):
22+
if with_gevent:
23+
gevent.monkey.patch_all()
24+
25+
import threading
26+
27+
# Need to explicitly call _get_contextvars because the SDK has already
28+
# decided upon gevent on import.
29+
30+
from sentry_sdk import utils
31+
32+
_, ContextVar = utils._get_contextvars()
33+
34+
ts = []
35+
36+
var = ContextVar("test_contextvar_leaks")
37+
38+
success = []
39+
40+
def run():
41+
value = int(random.random() * 1000)
42+
var.set(value)
43+
44+
for _ in range(100):
45+
time.sleep(0)
46+
assert var.get(None) == value
47+
48+
success.append(1)
49+
50+
for _ in range(20):
51+
t = threading.Thread(target=run)
52+
t.start()
53+
ts.append(t)
54+
55+
for t in ts:
56+
t.join()
57+
58+
assert len(success) == 20

0 commit comments

Comments
 (0)