@@ -908,7 +908,6 @@ class is implemented.
908
908
self ._ident = None
909
909
if _HAVE_THREAD_NATIVE_ID :
910
910
self ._native_id = None
911
- self ._running_lock = None
912
911
self ._tstate_lock = None
913
912
self ._started = Event ()
914
913
self ._is_stopped = False
@@ -927,17 +926,13 @@ def _reset_internal_locks(self, is_alive):
927
926
# bpo-42350: If the fork happens when the thread is already stopped
928
927
# (ex: after threading._shutdown() has been called), _tstate_lock
929
928
# is None. Do nothing in this case.
930
- if self ._running_lock is not None :
931
- self ._running_lock ._at_fork_reinit ()
932
- self ._running_lock .acquire ()
933
929
if self ._tstate_lock is not None :
934
930
self ._tstate_lock ._at_fork_reinit ()
935
931
self ._tstate_lock .acquire ()
936
932
else :
937
933
# The thread isn't alive after fork: it doesn't have a tstate
938
934
# anymore.
939
935
self ._is_stopped = True
940
- self ._running_lock = None
941
936
self ._tstate_lock = None
942
937
943
938
def __repr__ (self ):
@@ -1024,14 +1019,6 @@ def _set_ident(self):
1024
1019
def _set_native_id (self ):
1025
1020
self ._native_id = get_native_id ()
1026
1021
1027
- def _set_running_lock (self ):
1028
- """
1029
- Set a lock object which will be released by the interpreter when
1030
- the target func has finished running.
1031
- """
1032
- self ._running_lock = _allocate_lock ()
1033
- self ._running_lock .acquire ()
1034
-
1035
1022
def _set_tstate_lock (self ):
1036
1023
"""
1037
1024
Set a lock object which will be released by the interpreter when
@@ -1048,7 +1035,6 @@ def _set_tstate_lock(self):
1048
1035
def _bootstrap_inner (self ):
1049
1036
try :
1050
1037
self ._set_ident ()
1051
- self ._set_running_lock ()
1052
1038
self ._set_tstate_lock ()
1053
1039
if _HAVE_THREAD_NATIVE_ID :
1054
1040
self ._set_native_id ()
@@ -1068,29 +1054,29 @@ def _bootstrap_inner(self):
1068
1054
self ._invoke_excepthook (self )
1069
1055
finally :
1070
1056
self ._delete ()
1071
- self ._running_lock .release ()
1072
1057
1073
1058
def _stop (self ):
1074
1059
# After calling ._stop(), .is_alive() returns False and .join() returns
1075
- # immediately. ._running_lock must be released before calling ._stop().
1060
+ # immediately. ._tstate_lock must be released before calling ._stop().
1076
1061
#
1077
- # Normal case: ._bootstrap_inner() releases ._running_lock, and
1078
- # that's detected by our ._wait_for_running_lock(), called by .join()
1062
+ # Normal case: C code at the end of the thread's life
1063
+ # (release_sentinel in _threadmodule.c) releases ._tstate_lock, and
1064
+ # that's detected by our ._wait_for_tstate_lock(), called by .join()
1079
1065
# and .is_alive(). Any number of threads _may_ call ._stop()
1080
1066
# simultaneously (for example, if multiple threads are blocked in
1081
1067
# .join() calls), and they're not serialized. That's harmless -
1082
1068
# they'll just make redundant rebindings of ._is_stopped and
1083
- # ._running_lock . Obscure: we rebind ._running_lock last so that the
1084
- # "assert self._is_stopped" in ._wait_for_running_lock () always works
1085
- # (the assert is executed only if ._running_lock is None).
1069
+ # ._tstate_lock . Obscure: we rebind ._tstate_lock last so that the
1070
+ # "assert self._is_stopped" in ._wait_for_tstate_lock () always works
1071
+ # (the assert is executed only if ._tstate_lock is None).
1086
1072
#
1087
- # Special case: _main_thread releases ._running_lock via this
1073
+ # Special case: _main_thread releases ._tstate_lock via this
1088
1074
# module's _shutdown() function.
1089
- lock = self ._running_lock
1075
+ lock = self ._tstate_lock
1090
1076
if lock is not None :
1091
1077
assert not lock .locked ()
1092
1078
self ._is_stopped = True
1093
- self ._running_lock = None
1079
+ self ._tstate_lock = None
1094
1080
if not self .daemon :
1095
1081
with _shutdown_locks_lock :
1096
1082
# Remove our lock and other released locks from _shutdown_locks
@@ -1137,17 +1123,20 @@ def join(self, timeout=None):
1137
1123
raise RuntimeError ("cannot join current thread" )
1138
1124
1139
1125
if timeout is None :
1140
- self ._wait_for_running_lock ()
1126
+ self ._wait_for_tstate_lock ()
1141
1127
else :
1142
1128
# the behavior of a negative timeout isn't documented, but
1143
1129
# historically .join(timeout=x) for x<0 has acted as if timeout=0
1144
- self ._wait_for_running_lock (timeout = max (timeout , 0 ))
1145
-
1146
- def _wait_for_running_lock (self , block = True , timeout = - 1 ):
1147
- # This method passes its arguments to _running_lock.acquire().
1148
- # If the lock is acquired, the python code is done, and self._stop() is
1149
- # called. That sets ._is_stopped to True, and ._running_lock to None.
1150
- lock = self ._running_lock
1130
+ self ._wait_for_tstate_lock (timeout = max (timeout , 0 ))
1131
+
1132
+ def _wait_for_tstate_lock (self , block = True , timeout = - 1 ):
1133
+ # Issue #18808: wait for the thread state to be gone.
1134
+ # At the end of the thread's life, after all knowledge of the thread
1135
+ # is removed from C data structures, C code releases our _tstate_lock.
1136
+ # This method passes its arguments to _tstate_lock.acquire().
1137
+ # If the lock is acquired, the C code is done, and self._stop() is
1138
+ # called. That sets ._is_stopped to True, and ._tstate_lock to None.
1139
+ lock = self ._tstate_lock
1151
1140
if lock is None :
1152
1141
# already determined that the C code is done
1153
1142
assert self ._is_stopped
@@ -1218,7 +1207,7 @@ def is_alive(self):
1218
1207
assert self ._initialized , "Thread.__init__() not called"
1219
1208
if self ._is_stopped or not self ._started .is_set ():
1220
1209
return False
1221
- self ._wait_for_running_lock (False )
1210
+ self ._wait_for_tstate_lock (False )
1222
1211
return not self ._is_stopped
1223
1212
1224
1213
@property
@@ -1428,7 +1417,7 @@ class _MainThread(Thread):
1428
1417
1429
1418
def __init__ (self ):
1430
1419
Thread .__init__ (self , name = "MainThread" , daemon = False )
1431
- self ._set_running_lock ()
1420
+ self ._set_tstate_lock ()
1432
1421
self ._started .set ()
1433
1422
self ._set_ident ()
1434
1423
if _HAVE_THREAD_NATIVE_ID :
@@ -1569,7 +1558,7 @@ def _shutdown():
1569
1558
# dubious, but some code does it. We can't wait for C code to release
1570
1559
# the main thread's tstate_lock - that won't happen until the interpreter
1571
1560
# is nearly dead. So we release it here. Note that just calling _stop()
1572
- # isn't enough: other threads may already be waiting on _running_lock .
1561
+ # isn't enough: other threads may already be waiting on _tstate_lock .
1573
1562
if _main_thread ._is_stopped :
1574
1563
# _shutdown() was already called
1575
1564
return
@@ -1584,13 +1573,12 @@ def _shutdown():
1584
1573
1585
1574
# Main thread
1586
1575
if _main_thread .ident == get_ident ():
1587
- assert _main_thread ._tstate_lock is None
1588
- running_lock = _main_thread ._running_lock
1589
- # The main thread isn't finished yet, so its running lock can't
1576
+ tlock = _main_thread ._tstate_lock
1577
+ # The main thread isn't finished yet, so its thread state lock can't
1590
1578
# have been released.
1591
- assert running_lock is not None
1592
- assert running_lock .locked ()
1593
- running_lock .release ()
1579
+ assert tlock is not None
1580
+ assert tlock .locked ()
1581
+ tlock .release ()
1594
1582
_main_thread ._stop ()
1595
1583
else :
1596
1584
# bpo-1596321: _shutdown() must be called in the main thread.
0 commit comments