Skip to content

[3.9] bpo-41503: Fix race between setTarget and flush in logging.handlers.MemoryHandler (GH-21765) #21897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Lib/logging/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,11 @@ def setTarget(self, target):
"""
Set the target handler for this handler.
"""
self.target = target
self.acquire()
try:
self.target = target
finally:
self.release()

def flush(self):
"""
Expand Down
21 changes: 21 additions & 0 deletions Lib/test/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,27 @@ def test_flush_on_close(self):
# assert that no new lines have been added
self.assert_log_lines(lines) # no change

def test_race_between_set_target_and_flush(self):
class MockRaceConditionHandler:
def __init__(self, mem_hdlr):
self.mem_hdlr = mem_hdlr

def removeTarget(self):
self.mem_hdlr.setTarget(None)

def handle(self, msg):
t = threading.Thread(target=self.removeTarget)
t.daemon = True
t.start()

target = MockRaceConditionHandler(self.mem_hdlr)
self.mem_hdlr.setTarget(target)

for _ in range(10):
time.sleep(0.005)
self.mem_logger.info("not flushed")
self.mem_logger.warning("flushed")


class ExceptionFormatter(logging.Formatter):
"""A special exception formatter."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a race between setTarget and flush in logging.handlers.MemoryHandler.