Skip to content

Commit 29665a3

Browse files
committed
detect ctrl-c and stdin data
1 parent 1ee0066 commit 29665a3

File tree

9 files changed

+306
-84
lines changed

9 files changed

+306
-84
lines changed

crates/fspy/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ pub struct ChildTermination {
3838
}
3939

4040
pub struct TrackedChild {
41+
/// The process ID of the child.
42+
pub pid: u32,
43+
4144
/// The handle for writing to the child's standard input (stdin), if it has
4245
/// been captured.
4346
pub stdin: Option<ChildStdin>,

crates/fspy/src/unix/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ impl SpyImpl {
120120
.map_err(|err| SpawnError::OsSpawnError(err.into()))?
121121
.map_err(SpawnError::OsSpawnError)?;
122122

123+
// Get the PID before moving child into the wait_handle future
124+
let pid = child.id().expect("child process should have a pid");
125+
123126
Ok(TrackedChild {
127+
pid,
124128
stdin: child.stdin.take(),
125129
stdout: child.stdout.take(),
126130
stderr: child.stderr.take(),

crates/fspy/src/windows/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,11 @@ impl SpyImpl {
130130
}
131131
})?;
132132

133+
// Get the PID before moving child into the wait_handle future
134+
let pid = child.id().expect("child process should have a pid");
135+
133136
Ok(TrackedChild {
137+
pid,
134138
stdin: child.stdin.take(),
135139
stdout: child.stdout.take(),
136140
stderr: child.stderr.take(),

crates/vite_task/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ rusqlite = { workspace = true, features = ["bundled"] }
2929
serde = { workspace = true, features = ["derive", "rc"] }
3030
serde_json = { workspace = true }
3131
thiserror = { workspace = true }
32-
tokio = { workspace = true, features = ["rt-multi-thread", "io-std", "macros", "sync"] }
32+
tokio = { workspace = true, features = ["rt-multi-thread", "io-std", "macros", "sync", "signal"] }
3333
tracing = { workspace = true }
3434
twox-hash = { workspace = true }
3535
vite_glob = { workspace = true }

crates/vite_task/src/session/cache/display.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,16 @@ pub fn format_cache_update_status(status: &CacheUpdateStatus) -> Option<String>
304304
CacheNotUpdatedReason::CacheHit => None,
305305
CacheNotUpdatedReason::CacheDisabled => None,
306306
CacheNotUpdatedReason::BuiltInCommand => None,
307-
// This needs to be shown - task failed so cache wasn't updated
307+
// These need to be shown - they explain why cache wasn't updated
308308
CacheNotUpdatedReason::NonZeroExitStatus => {
309309
Some("→ Cache not updated: task failed".to_string())
310310
}
311+
CacheNotUpdatedReason::ReceivedCtrlC => {
312+
Some("→ Cache not updated: execution interrupted".to_string())
313+
}
314+
CacheNotUpdatedReason::StdinDataExists => {
315+
Some("→ Cache not updated: stdin had data".to_string())
316+
}
311317
},
312318
}
313319
}

crates/vite_task/src/session/event.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ pub enum CacheNotUpdatedReason {
2929
NonZeroExitStatus,
3030
/// Built-in command doesn't support caching
3131
BuiltInCommand,
32+
/// Ctrl+C was received during execution - cache invalidated for safety
33+
ReceivedCtrlC,
34+
/// Stdin had data - output may depend on input, unsafe to cache
35+
StdinDataExists,
3236
}
3337

3438
#[derive(Debug)]

crates/vite_task/src/session/execute/mod.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,21 @@ impl ExecutionContext<'_> {
287287
};
288288

289289
// 5. Update cache if successful and determine cache update status
290+
// Priority: NonZeroExitStatus > ReceivedCtrlC > StdinDataExists > Success
290291
let cache_update_status = if let Some((track_result, cache_metadata)) =
291292
track_result_with_cache_metadata
292293
{
293-
if result.exit_status.success() {
294-
// Execution succeeded, attempt cache update
294+
if !result.exit_status.success() {
295+
// Priority 1: Non-zero exit status - don't update cache
296+
CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::NonZeroExitStatus)
297+
} else if result.received_ctrl_c {
298+
// Priority 2: Received Ctrl+C - execution was interrupted, unsafe to cache
299+
CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::ReceivedCtrlC)
300+
} else if result.stdin_had_data {
301+
// Priority 3: Stdin had data - output may depend on input, unsafe to cache
302+
CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::StdinDataExists)
303+
} else {
304+
// Success: attempt cache update
295305
let fingerprint_ignores =
296306
cache_metadata.spawn_fingerprint.fingerprint_ignores().map(|v| v.as_slice());
297307
match PostRunFingerprint::create(
@@ -326,9 +336,6 @@ impl ExecutionContext<'_> {
326336
return Err(ExecutionAborted);
327337
}
328338
}
329-
} else {
330-
// Execution failed with non-zero exit status, don't update cache
331-
CacheUpdateStatus::NotUpdated(CacheNotUpdatedReason::NonZeroExitStatus)
332339
}
333340
} else {
334341
// Caching was disabled for this task

0 commit comments

Comments
 (0)