11use std:: path:: PathBuf ;
22use std:: env;
33use std:: process:: Stdio ;
4- use std:: sync:: Arc ;
54use std:: collections:: HashMap ;
65
76#[ cfg( unix) ]
@@ -43,8 +42,6 @@ use crate::{
4342} ;
4443
4544pub struct LocalApp {
46- ctx : tower_telemetry:: Context ,
47-
4845 status : Mutex < Option < Status > > ,
4946
5047 // waiter is what we use to communicate that the overall process is finished by the execution
@@ -157,6 +154,18 @@ async fn execute_local_app(opts: StartOptions, sx: oneshot::Sender<i32>, cancel_
157154 }
158155 }
159156
157+ // We insert these checks for cancellation along the way to see if the process was
158+ // terminated by someone.
159+ //
160+ // We do this before instantiating `Uv` because that can be somewhat time consuming. Likewise
161+ // this stops us from instantiating a bash process.
162+ if cancel_token. is_cancelled ( ) {
163+ // if there's a waiter, we want them to know that the process was cancelled so we have
164+ // to return something on the relevant channel.
165+ let _ = sx. send ( -1 ) ;
166+ return Err ( Error :: Cancelled ) ;
167+ }
168+
160169 if is_bash_package ( & package) {
161170 let child = execute_bash_program (
162171 & ctx,
@@ -177,6 +186,14 @@ async fn execute_local_app(opts: StartOptions, sx: oneshot::Sender<i32>, cancel_
177186 // Now we also need to find the program to execute.
178187 let program_path = package_path. join ( & manifest. invoke ) ;
179188
189+ // Check once more if the process was cancelled before we do a uv sync. The sync itself,
190+ // once started, will take a while and we have logic for checking for cancellation.
191+ if cancel_token. is_cancelled ( ) {
192+ // again tell any waiters that we cancelled.
193+ let _ = sx. send ( -1 ) ;
194+ return Err ( Error :: Cancelled ) ;
195+ }
196+
180197 let mut child = uv. sync ( & package_path, & env_vars) . await ?;
181198
182199 // Drain the logs to the output channel.
@@ -191,6 +208,14 @@ async fn execute_local_app(opts: StartOptions, sx: oneshot::Sender<i32>, cancel_
191208 // Let's wait for the setup to finish. We don't care about the results.
192209 wait_for_process ( ctx. clone ( ) , & cancel_token, child) . await ;
193210
211+ // Check once more to see if the process was cancelled, this will bail us out early.
212+ if cancel_token. is_cancelled ( ) {
213+ // if there's a waiter, we want them to know that the process was cancelled so we have
214+ // to return something on the relevant channel.
215+ let _ = sx. send ( -1 ) ;
216+ return Err ( Error :: Cancelled ) ;
217+ }
218+
194219 let mut child = uv. run ( & package_path, & program_path, & env_vars) . await ?;
195220
196221 // Drain the logs to the output channel.
@@ -205,12 +230,12 @@ async fn execute_local_app(opts: StartOptions, sx: oneshot::Sender<i32>, cancel_
205230 let _ = sx. send ( wait_for_process ( ctx. clone ( ) , & cancel_token, child) . await ) ;
206231 }
207232
233+ // Everything was properly executed I suppose.
208234 return Ok ( ( ) )
209235}
210236
211237impl App for LocalApp {
212238 async fn start ( opts : StartOptions ) -> Result < Self , Error > {
213- let ctx = opts. ctx . clone ( ) ;
214239 let cancel_token = CancellationToken :: new ( ) ;
215240 let terminator = Mutex :: new ( cancel_token. clone ( ) ) ;
216241
@@ -221,7 +246,6 @@ impl App for LocalApp {
221246 let execute_handle = Some ( handle) ;
222247
223248 Ok ( Self {
224- ctx,
225249 execute_handle,
226250 terminator,
227251 waiter,
@@ -262,7 +286,7 @@ impl App for LocalApp {
262286
263287 // Now we should wait for the join handle to finish.
264288 if let Some ( execute_handle) = self . execute_handle . take ( ) {
265- execute_handle. await ;
289+ let _ = execute_handle. await ;
266290 self . execute_handle = None ;
267291 }
268292
0 commit comments