@@ -75,29 +75,53 @@ def _reentrant_call_error(self):
7575        raise  ReentrantCallError (
7676            "Reentrant call into the multiprocessing resource tracker" )
7777
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 
91115
92-              _ , status  =  os . waitpid (self ._pid , 0 )
116+         _ , status  =  waitpid (self ._pid , 0 )
93117
94-              self ._pid  =  None 
118+         self ._pid  =  None 
95119
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 
101125
102126    def  getfd (self ):
103127        self .ensure_running ()
0 commit comments