Skip to content

Commit bc3df3e

Browse files
lzaoralkdudka
andcommitted
worker: fix deadlock when LoggingThread wrote into its own Queue
If self._hub.upload_task_log() called self._queue.put(), it would cause deadlock because 1. self._queue uses locks that are not reentrant. 2. it will block if the Queue is already full. Co-authored-by: Kamil Dudka <[email protected]> Co-authored-by: Lukáš Zaoral <[email protected]>
1 parent af73a03 commit bc3df3e

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

kobo/worker/logger.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __init__(self, hub, task_id, *args, **kwargs):
2424
self._buffer_size = kwargs.pop('buffer_size', 256)
2525
self._queue = queue.Queue(maxsize=self._buffer_size)
2626
self._event = threading.Event()
27+
self._in_logger_call = False
2728
self._running = True
2829
self._send_time = 0
2930
self._send_data = b""
@@ -88,8 +89,24 @@ def run(self):
8889

8990
def write(self, data):
9091
"""Add data to the queue and set the event for sending queue content."""
91-
self._queue.put(data)
92-
self._event.set()
92+
if threading.get_ident() != self.ident:
93+
self._queue.put(data)
94+
self._event.set()
95+
96+
# If self._hub.upload_task_log() called self._queue.put(), it would
97+
# cause deadlock because self._queue uses locks that are not reentrant
98+
# and queue may already be full.
99+
#
100+
# Log only data with printable characters.
101+
elif self._logger and data.strip():
102+
# Prevent infinite recursion if this thread is also used for the
103+
# logger output.
104+
if self._in_logger_call:
105+
return
106+
107+
self._in_logger_call = True
108+
self._logger.log_error("Error in LoggingThread: %r", data)
109+
self._in_logger_call = False
93110

94111
def stop(self):
95112
"""Send remaining data to hub and finish."""

0 commit comments

Comments
 (0)