gardesk/garcard / b81c372

Browse files

Fallback when prompt session cancels instantly

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
b81c372a96376f2747014ee7fd54e5b2c1ff586d
Parents
ba4cae5
Tree
bbbcd7e

1 changed file

StatusFile+-
M garcard/src/prompt.rs 39 4
garcard/src/prompt.rsmodified
@@ -4,9 +4,11 @@ use crate::prompt_ui::{
44
 };
55
 use anyhow::{Context, Result};
66
 use std::process::{Command, ExitStatus};
7
+use std::time::{Duration, Instant};
78
 
89
 const DEFAULT_ASK_TIMEOUT_SECS: u64 = 120;
910
 const FEEDBACK_TIMEOUT_SECS: u64 = 1;
11
+const RAPID_CANCEL_THRESHOLD: Duration = Duration::from_millis(300);
1012
 
1113
 #[derive(Debug, Clone, Copy)]
1214
 enum PromptTone {
@@ -53,12 +55,14 @@ impl Default for CommandPrompt {
5355
 impl CommandPrompt {
5456
     fn run_prompt(&mut self, prompt: &str, visible: bool) -> Result<PromptResponse> {
5557
         if let Some(command) = self.prompt_command.as_deref() {
58
+            tracing::debug!(visible, "Using custom prompt command backend");
5659
             return run_custom_prompt_command(command, prompt, visible);
5760
         }
5861
 
5962
         let timeout_secs = self.prompt_timeout_secs;
6063
         let session_result = match self.ensure_session() {
6164
             Some(session) => {
65
+                tracing::debug!(visible, "Using persistent prompt session backend");
6266
                 let request = PromptRequest {
6367
                     message: prompt.to_string(),
6468
                     mode: if visible {
@@ -69,15 +73,27 @@ impl CommandPrompt {
6973
                     timeout_secs,
7074
                     tone: UiPromptTone::Default,
7175
                 };
72
-                Some(session.run(request))
76
+                let started = Instant::now();
77
+                Some((session.run(request), started.elapsed()))
7378
             }
7479
             None => None,
7580
         };
7681
 
77
-        if let Some(result) = session_result {
82
+        if let Some((result, elapsed)) = session_result {
7883
             match result {
7984
                 Ok(PromptExit::Submitted(value)) => return Ok(PromptResponse::Submitted(value)),
80
-                Ok(PromptExit::Canceled) => return Ok(PromptResponse::Canceled),
85
+                Ok(PromptExit::Canceled) => {
86
+                    if elapsed < RAPID_CANCEL_THRESHOLD {
87
+                        tracing::warn!(
88
+                            elapsed_ms = elapsed.as_millis(),
89
+                            "Persistent prompt session canceled immediately; falling back to subprocess prompt"
90
+                        );
91
+                        self.session = None;
92
+                        self.session_unavailable = true;
93
+                    } else {
94
+                        return Ok(PromptResponse::Canceled);
95
+                    }
96
+                }
8197
                 Ok(PromptExit::TimedOut) => return Ok(PromptResponse::TimedOut),
8298
                 Err(err) => {
8399
                     tracing::warn!(
@@ -91,7 +107,10 @@ impl CommandPrompt {
91107
         }
92108
 
93109
         match run_gartk_prompt_subcommand(prompt, visible, timeout_secs) {
94
-            Ok(response) => Ok(response),
110
+            Ok(response) => {
111
+                tracing::debug!(visible, response = ?response, "Prompt subprocess completed");
112
+                Ok(response)
113
+            }
95114
             Err(err) => {
96115
                 tracing::warn!(
97116
                     error = %err,
@@ -228,6 +247,14 @@ fn run_gartk_prompt_subcommand(
228247
         scrub_bytes(&mut output.stderr);
229248
         anyhow::bail!("garcard prompt subcommand unavailable: {}", stderr);
230249
     }
250
+    if !output.status.success() {
251
+        let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
252
+        tracing::debug!(
253
+            code = ?output.status.code(),
254
+            stderr = %stderr,
255
+            "Prompt subprocess exited non-success"
256
+        );
257
+    }
231258
 
232259
     let response = map_output_to_prompt_response(&output.status, &output.stdout);
233260
     scrub_bytes(&mut output.stdout);
@@ -274,6 +301,14 @@ fn run_systemd_ask_password(
274301
     let mut output = command
275302
         .output()
276303
         .context("failed to run systemd-ask-password")?;
304
+    if !output.status.success() {
305
+        let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
306
+        tracing::debug!(
307
+            code = ?output.status.code(),
308
+            stderr = %stderr,
309
+            "systemd-ask-password exited non-success"
310
+        );
311
+    }
277312
     let response = map_output_to_prompt_response(&output.status, &output.stdout);
278313
     scrub_bytes(&mut output.stdout);
279314
     scrub_bytes(&mut output.stderr);