1010import sys
1111from datetime import datetime
1212from datetime import timedelta
13+ from functools import partial
1314from typing import cast
1415from typing import TYPE_CHECKING
1516
@@ -131,21 +132,35 @@ def protocol_factory():
131132 return Process (transport , protocol , loop , no_output_timeout_secs = no_output_timeout_secs )
132133
133134
135+ def _handle_signal (proc , sig ):
136+ if sig in proc ._handled_signals :
137+ log .info (f"\n Caught { sig .name } again, killing the process ..." )
138+ proc .kill ()
139+ return
140+ log .info (
141+ f"\n Caught { sig .name } , terminating process ....\n Send { sig .name } again to kill the process."
142+ )
143+ proc ._handled_signals .append (sig )
144+ proc .terminate ()
145+
146+
134147async def _subprocess_run (
135- f ,
148+ future ,
136149 cmdline ,
137150 check = True ,
138151 no_output_timeout_secs : int | None = None ,
139152 capture : bool = False ,
153+ interactive : bool = False ,
140154):
141155 stdout = subprocess .PIPE
142156 stderr = subprocess .PIPE
143157 kwargs = {}
144- # Run in a separate program group
145- if sys .platform .startswith ("win" ):
146- kwargs ["creationflags" ] = subprocess .CREATE_NEW_PROCESS_GROUP
147- else :
148- kwargs ["preexec_fn" ] = os .setpgrp
158+ if interactive is False :
159+ # Run in a separate program group
160+ if sys .platform .startswith ("win" ):
161+ kwargs ["creationflags" ] = subprocess .CREATE_NEW_PROCESS_GROUP
162+ else :
163+ kwargs ["preexec_fn" ] = os .setpgrp
149164 proc = await _create_subprocess_exec (
150165 * cmdline ,
151166 stdout = stdout ,
@@ -156,25 +171,27 @@ async def _subprocess_run(
156171 capture = capture ,
157172 ** kwargs ,
158173 )
174+ proc ._handled_signals = []
159175 loop = asyncio .get_running_loop ()
160176 for signame in ("SIGINT" , "SIGTERM" ):
161177 sig = getattr (signal , signame )
162- loop .add_signal_handler (sig , proc . terminate )
178+ loop .add_signal_handler (sig , partial ( _handle_signal , proc , sig ) )
163179 stdout , stderr = await asyncio .shield (proc .communicate ())
164180 result = subprocess .CompletedProcess (
165181 args = cmdline ,
166182 stdout = stdout ,
167183 stderr = stderr ,
168184 returncode = proc .returncode ,
169185 )
170- f .set_result (result )
186+ future .set_result (result )
171187
172188
173189def run (
174190 * cmdline ,
175191 check = True ,
176192 no_output_timeout_secs : int | None = None ,
177193 capture : bool = False ,
194+ interactive : bool = False ,
178195) -> subprocess .CompletedProcess [str ]:
179196 """
180197 Run a command.
@@ -189,6 +206,7 @@ def run(
189206 check ,
190207 no_output_timeout_secs = no_output_timeout_secs ,
191208 capture = capture ,
209+ interactive = interactive ,
192210 )
193211 )
194212 result = future .result ()
0 commit comments