Skip to content

Commit 2353d77

Browse files
authored
bpo-41503: Fix race between setTarget and flush in logging.handlers.MemoryHandler (GH-21765)
1 parent fff3c28 commit 2353d77

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

Lib/logging/handlers.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,11 @@ def setTarget(self, target):
13241324
"""
13251325
Set the target handler for this handler.
13261326
"""
1327-
self.target = target
1327+
self.acquire()
1328+
try:
1329+
self.target = target
1330+
finally:
1331+
self.release()
13281332

13291333
def flush(self):
13301334
"""

Lib/test/test_logging.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,27 @@ def test_flush_on_close(self):
11601160
# assert that no new lines have been added
11611161
self.assert_log_lines(lines) # no change
11621162

1163+
def test_race_between_set_target_and_flush(self):
1164+
class MockRaceConditionHandler:
1165+
def __init__(self, mem_hdlr):
1166+
self.mem_hdlr = mem_hdlr
1167+
1168+
def removeTarget(self):
1169+
self.mem_hdlr.setTarget(None)
1170+
1171+
def handle(self, msg):
1172+
t = threading.Thread(target=self.removeTarget)
1173+
t.daemon = True
1174+
t.start()
1175+
1176+
target = MockRaceConditionHandler(self.mem_hdlr)
1177+
self.mem_hdlr.setTarget(target)
1178+
1179+
for _ in range(10):
1180+
time.sleep(0.005)
1181+
self.mem_logger.info("not flushed")
1182+
self.mem_logger.warning("flushed")
1183+
11631184

11641185
class ExceptionFormatter(logging.Formatter):
11651186
"""A special exception formatter."""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a race between setTarget and flush in logging.handlers.MemoryHandler.

0 commit comments

Comments
 (0)