Confusing behavior with `sys.monitoring.DISABLE`
Personne n'a encore pris cette issue.
- Langage dominant
- Python
- Étoiles
- 77.2k
- Forks
- 35.9k
- Métriques de merge des PR
- Métriques de PR en attente
Description
Bug report
Bug description:
# Adapted from https://github.com/python/cpython/blob/a5eeb832c2bbbd6ce1e9d545a553de926af468d5/Lib/test/test_monitoring.py#L670-L682
import sys
TEST_TOOL = 2
E = sys.monitoring.events
INSTRUMENTED_EVENTS = [
(E.PY_START, "start"),
# (E.PY_RETURN, "return"), # Uncomment this line leads to different behavior
]
class CounterWithDisable:
def __init__(self):
self.disable = False
self.count = 0
def __call__(self, *args):
print("cb", self)
self.count += 1
if self.disable:
return sys.monitoring.DISABLE
def foo(x):
return x + 1
def call_foo(x):
yield 2 * foo(x + 5)
def test():
sys.monitoring.use_tool_id(TEST_TOOL, "test")
for event, name in INSTRUMENTED_EVENTS:
print("Event", name)
try:
counter = CounterWithDisable()
counter.disable = True
sys.monitoring.register_callback(TEST_TOOL, event, counter)
sys.monitoring.set_events(TEST_TOOL, event)
list(call_foo(1))
print("counter.count", counter.count)
assert (counter.count < 4)
finally:
sys.monitoring.set_events(TEST_TOOL, 0)
sys.monitoring.register_callback(TEST_TOOL, event, None)
sys.monitoring.free_tool_id(TEST_TOOL)
print("First run".center(80, '='))
test()
print("Second run".center(80, '='))
test()
The above script prints:
===================================First run====================================
Event start
cb <__main__.CounterWithDisable object at 0x10944c0b0>
cb <__main__.CounterWithDisable object at 0x10944c0b0>
counter.count 2
===================================Second run===================================
Event start
counter.count 0
The first run "leaks" the disabled callback to the second run.
If I uncomment the line:
# (E.PY_RETURN, "return"), # Uncomment this line leads to different behavior
The script will print:
===================================First run====================================
Event start
cb <__main__.CounterWithDisable object at 0x10e34c1d0>
cb <__main__.CounterWithDisable object at 0x10e34c1d0>
counter.count 2
Event return
cb <__main__.CounterWithDisable object at 0x10e34c200>
cb <__main__.CounterWithDisable object at 0x10e34c200>
counter.count 2
===================================Second run===================================
Event start
cb <__main__.CounterWithDisable object at 0x10e34c2f0>
cb <__main__.CounterWithDisable object at 0x10e34c2f0>
counter.count 2
Event return
cb <__main__.CounterWithDisable object at 0x10e34c1d0>
cb <__main__.CounterWithDisable object at 0x10e34c1d0>
counter.count 2
It stops the "leaking".
This problem can be workarounded by calling sys.monitoring.restart_events() at the end of test(). But, it is not clear if it is necessary. This cpython test: https://github.com/python/cpython/blob/a5eeb832c2bbbd6ce1e9d545a553de926af468d5/Lib/test/test_monitoring.py#L670-L682
does not use sys.monitoring.restart_events().
CPython versions tested on:
3.12
Operating systems tested on:
Linux, macOS
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par exécuter le reproducer sur CPython 3.12 et comparez son comportement avec celui de Lib/test/test_monitoring.py aux lignes référencées. Suivez la façon dont sys.monitoring.DISABLE persiste d’une exécution de test() à l’autre et la façon dont restart_events() modifie ce comportement. Le travail est terminé lorsque le cycle de vie prévu du callback est établi, couvert par un test de régression, et que la réutilisation déroutante est résolue ou documentée.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- python
- Domaine
- devtools
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 35/100