From 9931a92c5f269ea0f46d10774317d17a0fe7d1a9 Mon Sep 17 00:00:00 2001 From: megaproxy Date: Tue, 26 May 2026 18:25:55 +0100 Subject: [PATCH] Idle probe: inline pane_id + watch list into bash script (drop positional args) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of "filter never suppresses": passing the target pane_id and watch names as positional args to `bash -c "..." _ ` had them silently dropped by wsl.exe's arg-passing layer. Inside bash, $1 and $@ were empty — the script always looked for `TILETOPIA_PANE_ID=` (no value), found nothing, exited 1. Fix: format the script string in Rust with pane_id and watch names already substituted. No positional args to bash → nothing for wsl.exe to drop. Both inputs are safe to inline (u64 and a compile-time const list); validation needed if user-supplied watch names ever land here. Two unit tests guard against regressing to the positional-arg shape. Also dropped the diagnostic info!() spam added during debugging — back to debug! in the happy path, single concise probed= line on each cache miss. Co-Authored-By: Claude Opus 4.7 (1M context) --- src-tauri/src/probe.rs | 104 +++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 36 deletions(-) diff --git a/src-tauri/src/probe.rs b/src-tauri/src/probe.rs index 4e422ab..e14237c 100644 --- a/src-tauri/src/probe.rs +++ b/src-tauri/src/probe.rs @@ -92,6 +92,13 @@ impl ProbeCache { // Slow path: re-probe. Drop the lock before shelling out so other // probes aren't blocked. let running = probe_pane(distro, pane_id, DEFAULT_WATCH_PROCESSES); + tracing::debug!( + target: "tiletopia_lib::probe", + distro = %distro, + pane_id, + running, + "probed" + ); let mut guard = self.cache.lock(); guard.insert( @@ -111,33 +118,29 @@ impl Default for ProbeCache { } } -/// Bash one-liner: for each watched process name, `pgrep -x` for it; for -/// each matching PID, check `/proc//environ` for an exact -/// `TILETOPIA_PANE_ID=` entry (null-separated, so we `tr` it to -/// newlines and exact-line-match with `grep -xF`). Exit 0 = match, 1 = no -/// match, anything else = probe failure (treated as `false` upstream — -/// see fail-safe note on `is_watch_process_running`). +/// Build a single-line bash script with the target pane_id and watch-list +/// **interpolated directly** into the script text. The earlier design +/// passed these as positional args (`bash -c "..." _ `) +/// but `wsl.exe`'s arg-passing layer silently dropped everything after the +/// `-c` script string, so `$1`/`$@` were always empty inside bash. +/// Interpolating from Rust sidesteps the whole arg-passing path. /// -/// `bash` (not `sh`) is required for process substitution `< <(pgrep ...)`. -/// Both bash and pgrep are installed by default on every WSL distro -/// tiletopia targets; if a minimal distro is missing them the probe falls -/// to "not running" and the pane goes idle normally (better than the v1 -/// fail-safe which kept suppressing forever). -const PROBE_SCRIPT: &str = r#" -target_id="$1" -shift -for name in "$@"; do - while IFS= read -r pid; do - [ -z "$pid" ] && continue - if [ -r "/proc/$pid/environ" ]; then - if tr '\0' '\n' < "/proc/$pid/environ" 2>/dev/null | grep -qxF "TILETOPIA_PANE_ID=$target_id"; then - exit 0 - fi - fi - done < <(pgrep -x "$name" 2>/dev/null) -done -exit 1 -"#; +/// Both inputs are safe to inline: `pane_id` is a `u64` (no metachars) and +/// `watched` is a compile-time const list. If future code wires user-supplied +/// process names through here, validate/escape them first. +/// +/// Returns exit 0 if any watched process running in this specific pane has +/// the matching `TILETOPIA_PANE_ID` env marker; exit 1 otherwise. +fn build_probe_script(pane_id: u64, watched: &[&str]) -> String { + let watch_list = watched + .iter() + .map(|n| format!("\"{n}\"")) + .collect::>() + .join(" "); + format!( + r#"target_id={pane_id}; for name in {watch_list}; do for pid in $(pgrep -x "$name" 2>/dev/null); do [ -z "$pid" ] && continue; if [ -r "/proc/$pid/environ" ]; then if tr '\0' '\n' < "/proc/$pid/environ" 2>/dev/null | grep -qxF "TILETOPIA_PANE_ID=$target_id"; then exit 0; fi; fi; done; done; exit 1"# + ) +} fn probe_pane(distro: &str, pane_id: u64, watched: &[&str]) -> bool { if !cfg!(windows) { @@ -150,19 +153,15 @@ fn probe_pane(distro: &str, pane_id: u64, watched: &[&str]) -> bool { return false; } - // Compose args: bash -c