@@ -75,29 +75,53 @@ def _reentrant_call_error(self):
75
75
raise ReentrantCallError (
76
76
"Reentrant call into the multiprocessing resource tracker" )
77
77
78
- def _stop (self ):
79
- with self ._lock :
80
- # This should not happen (_stop() isn't called by a finalizer)
81
- # but we check for it anyway.
82
- if self ._lock ._recursion_count () > 1 :
83
- return self ._reentrant_call_error ()
84
- if self ._fd is None :
85
- # not running
86
- return
87
-
88
- # closing the "alive" file descriptor stops main()
89
- os .close (self ._fd )
90
- self ._fd = None
78
+ def __del__ (self ):
79
+ # making sure child processess are cleaned before ResourceTracker
80
+ # gets destructed.
81
+ # see https://github.com/python/cpython/issues/88887
82
+ self ._stop (use_blocking_lock = False )
83
+
84
+ def _stop (self , use_blocking_lock = True ):
85
+ if use_blocking_lock :
86
+ with self ._lock :
87
+ self ._stop_locked ()
88
+ else :
89
+ acquired = self ._lock .acquire (blocking = False )
90
+ try :
91
+ self ._stop_locked ()
92
+ finally :
93
+ if acquired :
94
+ self ._lock .release ()
95
+
96
+ def _stop_locked (
97
+ self ,
98
+ close = os .close ,
99
+ waitpid = os .waitpid ,
100
+ waitstatus_to_exitcode = os .waitstatus_to_exitcode ,
101
+ ):
102
+ # This shouldn't happen (it might when called by a finalizer)
103
+ # so we check for it anyway.
104
+ if self ._lock ._recursion_count () > 1 :
105
+ return self ._reentrant_call_error ()
106
+ if self ._fd is None :
107
+ # not running
108
+ return
109
+ if self ._pid is None :
110
+ return
111
+
112
+ # closing the "alive" file descriptor stops main()
113
+ close (self ._fd )
114
+ self ._fd = None
91
115
92
- _ , status = os . waitpid (self ._pid , 0 )
116
+ _ , status = waitpid (self ._pid , 0 )
93
117
94
- self ._pid = None
118
+ self ._pid = None
95
119
96
- try :
97
- self ._exitcode = os . waitstatus_to_exitcode (status )
98
- except ValueError :
99
- # os.waitstatus_to_exitcode may raise an exception for invalid values
100
- self ._exitcode = None
120
+ try :
121
+ self ._exitcode = waitstatus_to_exitcode (status )
122
+ except ValueError :
123
+ # os.waitstatus_to_exitcode may raise an exception for invalid values
124
+ self ._exitcode = None
101
125
102
126
def getfd (self ):
103
127
self .ensure_running ()
0 commit comments