Skip to content

Commit bc4bd11

Browse files
committed
Add test that verifies one thread having logging supressed while it handles a
message does not block a different thread from handling a message on the same logger.
1 parent 7b68d12 commit bc4bd11

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

Lib/test/test_logging.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4200,6 +4200,64 @@ def emit(self, record):
42004200
logger.setLevel(logging.DEBUG)
42014201
logger.debug("boom")
42024202

4203+
@threading_helper.requires_working_threading()
4204+
def test_thread_supression_noninterference(self):
4205+
lock = threading.Lock()
4206+
logger = logging.getLogger("test_thread_supression_noninterference")
4207+
4208+
# Block on the first call, allow others through
4209+
#
4210+
# NOTE: We need to bypass the base class's lock, otherwise that will
4211+
# block multiple calls to the same handler itself.
4212+
class BlockOnceHandler(TestHandler):
4213+
def __init__(self, barrier):
4214+
super().__init__(support.Matcher())
4215+
self.barrier = barrier
4216+
4217+
def createLock(self):
4218+
self.lock = None
4219+
4220+
def handle(self, record):
4221+
self.emit(record)
4222+
4223+
def emit(self, record):
4224+
if self.barrier:
4225+
barrier = self.barrier
4226+
self.barrier = None
4227+
barrier.wait()
4228+
with lock:
4229+
pass
4230+
super().emit(record)
4231+
logger.info("blow up if not supressed")
4232+
4233+
barrier = threading.Barrier(2)
4234+
handler = BlockOnceHandler(barrier)
4235+
logger.addHandler(handler)
4236+
logger.setLevel(logging.DEBUG)
4237+
4238+
t1 = threading.Thread(target=logger.debug, args=("1",))
4239+
with lock:
4240+
4241+
# Ensure first thread is blocked in the handler, hence supressing logging...
4242+
t1.start()
4243+
barrier.wait()
4244+
4245+
# ...but the second thread should still be able to log...
4246+
t2 = threading.Thread(target=logger.debug, args=("2",))
4247+
t2.start()
4248+
t2.join(timeout=3)
4249+
4250+
self.assertEqual(len(handler.buffer), 1)
4251+
self.assertTrue(handler.matches(levelno=logging.DEBUG, message='2'))
4252+
4253+
# The first thread should still be blocked here
4254+
self.assertTrue(t1.is_alive())
4255+
4256+
# Now the lock has been released the first thread should complete
4257+
t1.join()
4258+
self.assertEqual(len(handler.buffer), 2)
4259+
self.assertTrue(handler.matches(levelno=logging.DEBUG, message='1'))
4260+
42034261
class ManagerTest(BaseTest):
42044262
def test_manager_loggerclass(self):
42054263
logged = []

0 commit comments

Comments
 (0)