From 7d1d9121d6fa52345e498cd6f39d4d14692e3b0a Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 15 Jul 2021 16:09:05 +0100 Subject: [PATCH 1/3] Check for interrupts on any backwards edge. --- Lib/test/test_threading.py | 14 ++++++++++++++ Python/ceval.c | 7 ++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index f648a8b2bc52f5..180467ed2bd24f 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1604,6 +1604,20 @@ def test_interrupt_main_invalid_signal(self): self.assertRaises(ValueError, _thread.interrupt_main, signal.NSIG) self.assertRaises(ValueError, _thread.interrupt_main, 1000000) + def test_can_interrupt_tight_loops(self): + #Nothing to assert here. It just shouldn't hang. + + cont = True + def worker(): + while cont: + pass + + t = threading.Thread(target=worker) + t.start() + time.sleep(0.1) + cont = False + t.join() + class AtexitTests(unittest.TestCase): diff --git a/Python/ceval.c b/Python/ceval.c index a6eb83a4909d72..90112aa3f9476e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3638,14 +3638,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) if (Py_IsFalse(cond)) { Py_DECREF(cond); JUMPTO(oparg); + CHECK_EVAL_BREAKER(); DISPATCH(); } err = PyObject_IsTrue(cond); Py_DECREF(cond); if (err > 0) ; - else if (err == 0) + else if (err == 0) { JUMPTO(oparg); + CHECK_EVAL_BREAKER(); + } else goto error; DISPATCH(); @@ -3662,12 +3665,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) if (Py_IsTrue(cond)) { Py_DECREF(cond); JUMPTO(oparg); + CHECK_EVAL_BREAKER(); DISPATCH(); } err = PyObject_IsTrue(cond); Py_DECREF(cond); if (err > 0) { JUMPTO(oparg); + CHECK_EVAL_BREAKER(); } else if (err == 0) ; From e52abd2e97684a96d9a37b4b33d781010c582ee1 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 15 Jul 2021 17:24:17 +0100 Subject: [PATCH 2/3] Make sure test cleans up and doesn't race. --- Lib/test/test_threading.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 180467ed2bd24f..cd93ef7862b361 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1604,17 +1604,22 @@ def test_interrupt_main_invalid_signal(self): self.assertRaises(ValueError, _thread.interrupt_main, signal.NSIG) self.assertRaises(ValueError, _thread.interrupt_main, 1000000) + @threading_helper.reap_threads def test_can_interrupt_tight_loops(self): #Nothing to assert here. It just shouldn't hang. cont = True + started = False def worker(): + nonlocal started + started = True while cont: pass t = threading.Thread(target=worker) t.start() - time.sleep(0.1) + while not started: + pass cont = False t.join() From 413dffd117baee6fda798965cfdb23c4d37b14ad Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 15 Jul 2021 18:46:19 +0100 Subject: [PATCH 3/3] Make sure that tight loop interruption test terminates eventually. --- Lib/test/test_threading.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index cd93ef7862b361..23fe2d3f4d32e2 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1606,22 +1606,28 @@ def test_interrupt_main_invalid_signal(self): @threading_helper.reap_threads def test_can_interrupt_tight_loops(self): - #Nothing to assert here. It just shouldn't hang. - - cont = True - started = False - def worker(): - nonlocal started - started = True - while cont: + cont = [True] + started = [False] + interrupted = [False] + + def worker(started, cont, interrupted): + iterations = 100_000_000 + started[0] = True + while cont[0]: + if iterations: + iterations -= 1 + else: + return pass + interrupted[0] = True - t = threading.Thread(target=worker) + t = threading.Thread(target=worker,args=(started, cont, interrupted)) t.start() - while not started: + while not started[0]: pass - cont = False + cont[0] = False t.join() + self.assertTrue(interrupted[0]) class AtexitTests(unittest.TestCase): pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy