Skip to content

Commit 85cc477

Browse files
authored
Merge pull request #18 from code4mk/windows-support
Split foreground_pid by platform: ConPTY has no process groups
2 parents 3dcfadc + 936f1b2 commit 85cc477

3 files changed

Lines changed: 39 additions & 9 deletions

File tree

‎docs/WINDOWS-SUPPORT.md‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,13 @@ by accident, and it breaks the moment an NSIS `.exe` is published alongside it.
141141

142142
- **"A command is running" check.** `PtyInstance::foreground_pid()` compares the
143143
tty's foreground process group against the shell's pid. ConPTY has no process
144-
groups, so this returns `None` — which the code already treats as idle. The
145-
practical effect is that the confirmation before restarting to install an
146-
update won't fire on Windows. Safe direction (a missed prompt, not a wrong
147-
action), but it should be documented rather than discovered.
144+
groups at all, and `portable-pty` reflects that by declaring
145+
`process_group_leader` only under `#[cfg(unix)]` — so this is a *compile*
146+
error on Windows, not a method that returns `None`. `foreground_pid` is now
147+
two implementations, and the Windows one returns `None`, which callers already
148+
read as idle. The practical effect is that the confirmation before restarting
149+
to install an update won't fire on Windows: a missed prompt rather than a
150+
wrong action.
148151
- **Spec storage.** `~/.figyterm` becomes `%USERPROFILE%\.figyterm`, which works
149152
but isn't idiomatic — `%APPDATA%\figyterm` is. Same call as the XDG question on
150153
Linux, and the same answer: low priority.

‎docs/WINDOWS-TASKS.md‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,17 @@ Windows · `[ ]` todo
99
Everything below marked `[x]` was written and type-checked, but **nothing has run
1010
on Windows**. The Rust Windows branches were compiled for
1111
`x86_64-pc-windows-msvc` in isolation (the full crate can't cross-check here —
12-
`ring` needs a Windows C toolchain), and the path logic is covered by unit tests
13-
that deliberately run on any host. §8 is the part that still needs a real box.
12+
`ring`, via the updater plugin, needs a Windows C toolchain), and the path logic
13+
is covered by unit tests that deliberately run on any host. §8 is the part that
14+
still needs a real box.
15+
16+
That isolation has a known blind spot, and it has already cost one round trip:
17+
it checks the code *this port wrote*, not pre-existing code that the Windows
18+
target newly compiles. `foreground_pid()` calling a `#[cfg(unix)]` trait method
19+
was found by a real Windows build, not by anything here. A crate-wide audit for
20+
other unix-only APIs (`std::os::unix`, `libc`, `nix`, `PermissionsExt`, …) came
21+
back empty, so that was the only one — but the first real build is still the
22+
authority.
1423

1524
---
1625

@@ -83,8 +92,9 @@ that deliberately run on any host. §8 is the part that still needs a real box.
8392
table (it shares Linux's `Ctrl+Shift` scheme).
8493
- [x] **`RELEASING.md`** — the Windows job and which artifact the updater uses.
8594
- [x] **Document the degradations** — the "a command is running" guard can't fire
86-
on Windows (ConPTY has no process groups, so `foreground_pid()` always
87-
returns `None`, which reads as idle).
95+
on Windows: ConPTY has no process groups, and `portable-pty` declares
96+
`process_group_leader` under `#[cfg(unix)]`, so `foreground_pid()` is
97+
`#[cfg]`-split and returns `None` there. Callers read that as idle.
8898

8999
## 8. Verification
90100

‎src-tauri/src/terminal/pty.rs‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,9 @@ pub struct PtyInstance {
151151
pub master: Arc<Mutex<Box<dyn MasterPty + Send>>>,
152152
pub writer: Arc<Mutex<Box<dyn Write + Send>>>,
153153
/// PID of the login shell itself. When the tty's foreground process group
154-
/// leader differs from this, the user is running something.
154+
/// leader differs from this, the user is running something. Unread on
155+
/// Windows, where there are no process groups to compare it against.
156+
#[cfg_attr(windows, allow(dead_code))]
155157
shell_pid: Option<u32>,
156158
shutdown: Arc<Mutex<bool>>,
157159
}
@@ -257,13 +259,28 @@ impl PtyInstance {
257259
/// `None` means idle (or undeterminable, which is treated as idle: a false
258260
/// "busy" would block updating forever, while a false "idle" only costs the
259261
/// user a confirmation they'd have clicked through anyway).
262+
#[cfg(unix)]
260263
pub fn foreground_pid(&self) -> Option<u32> {
261264
let shell_pid = self.shell_pid?;
262265
let master = self.master.lock().ok()?;
263266
let leader = master.process_group_leader()? as u32;
264267
(leader != shell_pid).then_some(leader)
265268
}
266269

270+
/// Always `None` on Windows.
271+
///
272+
/// The question doesn't exist there: ConPTY has no process groups, and
273+
/// `portable-pty` reflects that by declaring `process_group_leader` only
274+
/// under `#[cfg(unix)]` — so this isn't a stub for something unimplemented,
275+
/// it's the whole answer the platform can give.
276+
///
277+
/// Callers read `None` as idle, which errs the safe way: the update flow
278+
/// simply won't name a running command before restarting.
279+
#[cfg(windows)]
280+
pub fn foreground_pid(&self) -> Option<u32> {
281+
None
282+
}
283+
267284
pub fn write(&self, data: &[u8]) -> Result<(), String> {
268285
let mut writer = self.writer.lock().map_err(|e| e.to_string())?;
269286
writer.write_all(data).map_err(|e| format!("Write failed: {}", e))?;

0 commit comments

Comments
 (0)