@@ -159,12 +159,9 @@ def addLevelName(level, levelName):
159
159
160
160
This is used when converting levels to text during message formatting.
161
161
"""
162
- _acquireLock ()
163
- try : #unlikely to cause an exception, but you never know...
162
+ with _lock :
164
163
_levelToName [level ] = levelName
165
164
_nameToLevel [levelName ] = level
166
- finally :
167
- _releaseLock ()
168
165
169
166
if hasattr (sys , "_getframe" ):
170
167
currentframe = lambda : sys ._getframe (1 )
@@ -231,25 +228,27 @@ def _checkLevel(level):
231
228
#
232
229
_lock = threading .RLock ()
233
230
234
- def _acquireLock ():
231
+ def _prepareFork ():
235
232
"""
236
- Acquire the module-level lock for serializing access to shared data .
233
+ Prepare to fork a new child process by acquiring the module-level lock .
237
234
238
- This should be released with _releaseLock ().
235
+ This should be used in conjunction with _afterFork ().
239
236
"""
240
- if _lock :
241
- try :
242
- _lock .acquire ()
243
- except BaseException :
244
- _lock .release ()
245
- raise
237
+ # Wrap the lock acquisition in a try-except to prevent the lock from being
238
+ # abandoned in the event of an asynchronous exception. See gh-106238.
239
+ try :
240
+ _lock .acquire ()
241
+ except BaseException :
242
+ _lock .release ()
243
+ raise
246
244
247
- def _releaseLock ():
245
+ def _afterFork ():
248
246
"""
249
- Release the module-level lock acquired by calling _acquireLock().
247
+ After a new child process has been forked, release the module-level lock.
248
+
249
+ This should be used in conjunction with _prepareFork().
250
250
"""
251
- if _lock :
252
- _lock .release ()
251
+ _lock .release ()
253
252
254
253
255
254
# Prevent a held logging lock from blocking a child from logging.
@@ -264,23 +263,20 @@ def _register_at_fork_reinit_lock(instance):
264
263
_at_fork_reinit_lock_weakset = weakref .WeakSet ()
265
264
266
265
def _register_at_fork_reinit_lock (instance ):
267
- _acquireLock ()
268
- try :
266
+ with _lock :
269
267
_at_fork_reinit_lock_weakset .add (instance )
270
- finally :
271
- _releaseLock ()
272
268
273
269
def _after_at_fork_child_reinit_locks ():
274
270
for handler in _at_fork_reinit_lock_weakset :
275
271
handler ._at_fork_reinit ()
276
272
277
- # _acquireLock () was called in the parent before forking.
273
+ # _prepareFork () was called in the parent before forking.
278
274
# The lock is reinitialized to unlocked state.
279
275
_lock ._at_fork_reinit ()
280
276
281
- os .register_at_fork (before = _acquireLock ,
277
+ os .register_at_fork (before = _prepareFork ,
282
278
after_in_child = _after_at_fork_child_reinit_locks ,
283
- after_in_parent = _releaseLock )
279
+ after_in_parent = _afterFork )
284
280
285
281
286
282
#---------------------------------------------------------------------------
@@ -883,25 +879,20 @@ def _removeHandlerRef(wr):
883
879
# set to None. It can also be called from another thread. So we need to
884
880
# pre-emptively grab the necessary globals and check if they're None,
885
881
# to prevent race conditions and failures during interpreter shutdown.
886
- acquire , release , handlers = _acquireLock , _releaseLock , _handlerList
887
- if acquire and release and handlers :
888
- acquire ()
889
- try :
890
- handlers .remove (wr )
891
- except ValueError :
892
- pass
893
- finally :
894
- release ()
882
+ handlers , lock = _handlerList , _lock
883
+ if lock and handlers :
884
+ with lock :
885
+ try :
886
+ handlers .remove (wr )
887
+ except ValueError :
888
+ pass
895
889
896
890
def _addHandlerRef (handler ):
897
891
"""
898
892
Add a handler to the internal cleanup list using a weak reference.
899
893
"""
900
- _acquireLock ()
901
- try :
894
+ with _lock :
902
895
_handlerList .append (weakref .ref (handler , _removeHandlerRef ))
903
- finally :
904
- _releaseLock ()
905
896
906
897
907
898
def getHandlerByName (name ):
@@ -946,15 +937,12 @@ def get_name(self):
946
937
return self ._name
947
938
948
939
def set_name (self , name ):
949
- _acquireLock ()
950
- try :
940
+ with _lock :
951
941
if self ._name in _handlers :
952
942
del _handlers [self ._name ]
953
943
self ._name = name
954
944
if name :
955
945
_handlers [name ] = self
956
- finally :
957
- _releaseLock ()
958
946
959
947
name = property (get_name , set_name )
960
948
@@ -1026,11 +1014,8 @@ def handle(self, record):
1026
1014
if isinstance (rv , LogRecord ):
1027
1015
record = rv
1028
1016
if rv :
1029
- self .acquire ()
1030
- try :
1017
+ with self .lock :
1031
1018
self .emit (record )
1032
- finally :
1033
- self .release ()
1034
1019
return rv
1035
1020
1036
1021
def setFormatter (self , fmt ):
@@ -1058,13 +1043,10 @@ def close(self):
1058
1043
methods.
1059
1044
"""
1060
1045
#get the module data lock, as we're updating a shared structure.
1061
- _acquireLock ()
1062
- try : #unlikely to raise an exception, but you never know...
1046
+ with _lock :
1063
1047
self ._closed = True
1064
1048
if self ._name and self ._name in _handlers :
1065
1049
del _handlers [self ._name ]
1066
- finally :
1067
- _releaseLock ()
1068
1050
1069
1051
def handleError (self , record ):
1070
1052
"""
@@ -1141,12 +1123,9 @@ def flush(self):
1141
1123
"""
1142
1124
Flushes the stream.
1143
1125
"""
1144
- self .acquire ()
1145
- try :
1126
+ with self .lock :
1146
1127
if self .stream and hasattr (self .stream , "flush" ):
1147
1128
self .stream .flush ()
1148
- finally :
1149
- self .release ()
1150
1129
1151
1130
def emit (self , record ):
1152
1131
"""
@@ -1182,12 +1161,9 @@ def setStream(self, stream):
1182
1161
result = None
1183
1162
else :
1184
1163
result = self .stream
1185
- self .acquire ()
1186
- try :
1164
+ with self .lock :
1187
1165
self .flush ()
1188
1166
self .stream = stream
1189
- finally :
1190
- self .release ()
1191
1167
return result
1192
1168
1193
1169
def __repr__ (self ):
@@ -1237,8 +1213,7 @@ def close(self):
1237
1213
"""
1238
1214
Closes the stream.
1239
1215
"""
1240
- self .acquire ()
1241
- try :
1216
+ with self .lock :
1242
1217
try :
1243
1218
if self .stream :
1244
1219
try :
@@ -1254,8 +1229,6 @@ def close(self):
1254
1229
# Also see Issue #42378: we also rely on
1255
1230
# self._closed being set to True there
1256
1231
StreamHandler .close (self )
1257
- finally :
1258
- self .release ()
1259
1232
1260
1233
def _open (self ):
1261
1234
"""
@@ -1391,8 +1364,7 @@ def getLogger(self, name):
1391
1364
rv = None
1392
1365
if not isinstance (name , str ):
1393
1366
raise TypeError ('A logger name must be a string' )
1394
- _acquireLock ()
1395
- try :
1367
+ with _lock :
1396
1368
if name in self .loggerDict :
1397
1369
rv = self .loggerDict [name ]
1398
1370
if isinstance (rv , PlaceHolder ):
@@ -1407,8 +1379,6 @@ def getLogger(self, name):
1407
1379
rv .manager = self
1408
1380
self .loggerDict [name ] = rv
1409
1381
self ._fixupParents (rv )
1410
- finally :
1411
- _releaseLock ()
1412
1382
return rv
1413
1383
1414
1384
def setLoggerClass (self , klass ):
@@ -1471,12 +1441,11 @@ def _clear_cache(self):
1471
1441
Called when level changes are made
1472
1442
"""
1473
1443
1474
- _acquireLock ()
1475
- for logger in self .loggerDict .values ():
1476
- if isinstance (logger , Logger ):
1477
- logger ._cache .clear ()
1478
- self .root ._cache .clear ()
1479
- _releaseLock ()
1444
+ with _lock :
1445
+ for logger in self .loggerDict .values ():
1446
+ if isinstance (logger , Logger ):
1447
+ logger ._cache .clear ()
1448
+ self .root ._cache .clear ()
1480
1449
1481
1450
#---------------------------------------------------------------------------
1482
1451
# Logger classes and functions
@@ -1701,23 +1670,17 @@ def addHandler(self, hdlr):
1701
1670
"""
1702
1671
Add the specified handler to this logger.
1703
1672
"""
1704
- _acquireLock ()
1705
- try :
1673
+ with _lock :
1706
1674
if not (hdlr in self .handlers ):
1707
1675
self .handlers .append (hdlr )
1708
- finally :
1709
- _releaseLock ()
1710
1676
1711
1677
def removeHandler (self , hdlr ):
1712
1678
"""
1713
1679
Remove the specified handler from this logger.
1714
1680
"""
1715
- _acquireLock ()
1716
- try :
1681
+ with _lock :
1717
1682
if hdlr in self .handlers :
1718
1683
self .handlers .remove (hdlr )
1719
- finally :
1720
- _releaseLock ()
1721
1684
1722
1685
def hasHandlers (self ):
1723
1686
"""
@@ -1795,16 +1758,13 @@ def isEnabledFor(self, level):
1795
1758
try :
1796
1759
return self ._cache [level ]
1797
1760
except KeyError :
1798
- _acquireLock ()
1799
- try :
1761
+ with _lock :
1800
1762
if self .manager .disable >= level :
1801
1763
is_enabled = self ._cache [level ] = False
1802
1764
else :
1803
1765
is_enabled = self ._cache [level ] = (
1804
1766
level >= self .getEffectiveLevel ()
1805
1767
)
1806
- finally :
1807
- _releaseLock ()
1808
1768
return is_enabled
1809
1769
1810
1770
def getChild (self , suffix ):
@@ -1834,16 +1794,13 @@ def _hierlevel(logger):
1834
1794
return 1 + logger .name .count ('.' )
1835
1795
1836
1796
d = self .manager .loggerDict
1837
- _acquireLock ()
1838
- try :
1797
+ with _lock :
1839
1798
# exclude PlaceHolders - the last check is to ensure that lower-level
1840
1799
# descendants aren't returned - if there are placeholders, a logger's
1841
1800
# parent field might point to a grandparent or ancestor thereof.
1842
1801
return set (item for item in d .values ()
1843
1802
if isinstance (item , Logger ) and item .parent is self and
1844
1803
_hierlevel (item ) == 1 + _hierlevel (item .parent ))
1845
- finally :
1846
- _releaseLock ()
1847
1804
1848
1805
def __repr__ (self ):
1849
1806
level = getLevelName (self .getEffectiveLevel ())
@@ -2102,8 +2059,7 @@ def basicConfig(**kwargs):
2102
2059
"""
2103
2060
# Add thread safety in case someone mistakenly calls
2104
2061
# basicConfig() from multiple threads
2105
- _acquireLock ()
2106
- try :
2062
+ with _lock :
2107
2063
force = kwargs .pop ('force' , False )
2108
2064
encoding = kwargs .pop ('encoding' , None )
2109
2065
errors = kwargs .pop ('errors' , 'backslashreplace' )
@@ -2152,8 +2108,6 @@ def basicConfig(**kwargs):
2152
2108
if kwargs :
2153
2109
keys = ', ' .join (kwargs .keys ())
2154
2110
raise ValueError ('Unrecognised argument(s): %s' % keys )
2155
- finally :
2156
- _releaseLock ()
2157
2111
2158
2112
#---------------------------------------------------------------------------
2159
2113
# Utility functions at module level.
0 commit comments