Skip to content

Commit a0c2cfb

Browse files
committed
Use the WeakSet approach per code review.
1 parent 64a53be commit a0c2cfb

File tree

1 file changed

+37
-3
lines changed

1 file changed

+37
-3
lines changed

Lib/logging/__init__.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,44 @@ def _releaseLock():
225225
if _lock:
226226
_lock.release()
227227

228+
228229
# Prevent a held logging lock from blocking a child from logging.
229230
os.register_at_fork(before=_acquireLock,
230231
after_in_child=_releaseLock,
231232
after_in_parent=_releaseLock)
232233

234+
235+
# A collection of instances with acquire and release methods (logging.Handler)
236+
# to be called before and after fork. The weakref avoids us keeping discarded
237+
# Handler instances alive forever in case an odd program creates and destroys
238+
# many over its lifetime.
239+
_at_fork_acquire_release_weakset = weakref.WeakSet()
240+
241+
242+
def _at_fork_weak_calls(method_name):
243+
for instance in _at_fork_acquire_release_weakset:
244+
method = getattr(instance, method_name)
245+
try:
246+
method()
247+
except Exception as err:
248+
# Similar to what PyErr_WriteUnraisable does.
249+
print("Ignoring exception from logging atfork", instance,
250+
method_name, "method:", err, file=sys.stderr)
251+
252+
253+
def _before_at_fork_weak_calls():
254+
_at_fork_weak_calls('acquire')
255+
256+
257+
def _after_at_fork_weak_calls():
258+
_at_fork_weak_calls('release')
259+
260+
261+
os.register_at_fork(before=_before_at_fork_weak_calls,
262+
after_in_child=_after_at_fork_weak_calls,
263+
after_in_parent=_after_at_fork_weak_calls)
264+
265+
233266
#---------------------------------------------------------------------------
234267
# The logging record
235268
#---------------------------------------------------------------------------
@@ -800,9 +833,10 @@ def createLock(self):
800833
Acquire a thread lock for serializing access to the underlying I/O.
801834
"""
802835
self.lock = threading.RLock()
803-
os.register_at_fork(before=self.acquire,
804-
after_in_child=self.release,
805-
after_in_parent=self.release)
836+
# We put the instance itself in a single WeakSet as we MUST have only
837+
# one atomic weak ref. used by both before and after atfork calls to
838+
# guarantee matched pairs of acquire and release calls.
839+
_at_fork_acquire_release_weakset.add(self)
806840

807841
def acquire(self):
808842
"""

0 commit comments

Comments
 (0)