@@ -225,11 +225,44 @@ def _releaseLock():
225
225
if _lock :
226
226
_lock .release ()
227
227
228
+
228
229
# Prevent a held logging lock from blocking a child from logging.
229
230
os .register_at_fork (before = _acquireLock ,
230
231
after_in_child = _releaseLock ,
231
232
after_in_parent = _releaseLock )
232
233
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
+
233
266
#---------------------------------------------------------------------------
234
267
# The logging record
235
268
#---------------------------------------------------------------------------
@@ -800,9 +833,10 @@ def createLock(self):
800
833
Acquire a thread lock for serializing access to the underlying I/O.
801
834
"""
802
835
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 )
806
840
807
841
def acquire (self ):
808
842
"""
0 commit comments