3333from pathlib import Path
3434from subprocess import CompletedProcess , Popen , TimeoutExpired
3535from tempfile import TemporaryDirectory
36- from threading import Event
36+ from threading import Event , Thread
3737from types import FrameType
3838from typing import Any , Callable , Dict , Iterator , List , Optional , Tuple , Union
3939
@@ -93,6 +93,7 @@ def start_process(
9393 cmd : Union [str , List [str ]],
9494 via_staticx : bool = False ,
9595 tmpdir : Optional [Path ] = None ,
96+ direct_call : bool = True ,
9697 ** kwargs : Any ,
9798) -> Popen :
9899 if isinstance (cmd , str ):
@@ -135,7 +136,16 @@ def start_process(
135136 env = env ,
136137 ** kwargs ,
137138 )
139+
140+ def process_exit_handler () -> None :
141+ process .communicate ()
142+ # Remove from _processes and do any cleanup
143+ cleanup_process_reference (process )
144+ logger .critical (f"Process { process .pid } exited, total processes tracked { len (_processes )} " )
145+
138146 _processes .append (process )
147+ if direct_call :
148+ Thread (target = process_exit_handler , daemon = True ).start ()
139149 return process
140150
141151
@@ -152,14 +162,6 @@ def wait_event(timeout: float, stop_event: Event, condition: Callable[[], bool],
152162 raise TimeoutError ()
153163
154164
155- def poll_process (process : Popen , timeout : float , stop_event : Event ) -> None :
156- try :
157- wait_event (timeout , stop_event , lambda : process .poll () is not None )
158- except StopEventSetException :
159- process .kill ()
160- raise
161-
162-
163165def remove_files_by_prefix (prefix : str ) -> None :
164166 for f in glob .glob (f"{ prefix } *" ):
165167 os .unlink (f )
@@ -228,7 +230,7 @@ def run_process(
228230 stderr : bytes
229231
230232 reraise_exc : Optional [BaseException ] = None
231- with start_process (cmd , via_staticx , ** kwargs ) as process :
233+ with start_process (cmd , via_staticx , direct_call = False , ** kwargs ) as process :
232234 assert isinstance (process .args , str ) or (
233235 isinstance (process .args , list ) and all (isinstance (s , str ) for s in process .args )
234236 ), process .args # mypy
@@ -536,6 +538,8 @@ def cleanup_process_reference(process: Popen) -> None:
536538def _exit_handler () -> None :
537539 for process in _processes :
538540 process .kill ()
541+ # remove process in _processes
542+ cleanup_process_reference (process )
539543
540544
541545def _sigint_handler (sig : int , frame : Optional [FrameType ]) -> None :
0 commit comments