Skip to content

Commit 6bc4872

Browse files
committed
PYTHON-1177 Fix race condition in PeriodicExecutor
1 parent 42c5df8 commit 6bc4872

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

pymongo/periodic_executor.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,27 @@ def __init__(self, interval, min_interval, target, name=None):
4747
self._thread = None
4848
self._name = name
4949

50+
self._thread_will_exit = False
51+
self._lock = threading.Lock()
52+
5053
def open(self):
5154
"""Start. Multiple calls have no effect.
5255
5356
Not safe to call from multiple threads at once.
5457
"""
55-
self._stopped = False
58+
with self._lock:
59+
if self._thread_will_exit:
60+
# If the background thread has read self._stopped as True
61+
# there is a chance that it has not yet exited. The call to
62+
# join should not block indefinitely because there is no
63+
# other work done outside the while loop in self._run.
64+
try:
65+
self._thread.join()
66+
except ReferenceError:
67+
# Thread terminated.
68+
pass
69+
self._thread_will_exit = False
70+
self._stopped = False
5671
started = False
5772
try:
5873
started = self._thread and self._thread.is_alive()
@@ -87,8 +102,15 @@ def wake(self):
87102
"""Execute the target function soon."""
88103
self._event = True
89104

105+
def __should_stop(self):
106+
with self._lock:
107+
if self._stopped:
108+
self._thread_will_exit = True
109+
return True
110+
return False
111+
90112
def _run(self):
91-
while not self._stopped:
113+
while not self.__should_stop():
92114
try:
93115
if not self._target():
94116
self._stopped = True

0 commit comments

Comments
 (0)