Fix bugs from a full audit: Tailscale recovery, SSID verification, captive portals, config races
The watch loop could spin forever on a stopped Tailscale daemon (the
auto-start path was unreachable) while re-notifying every retry, report
"connected" when NM autoconnect won a race onto a different SSID, and
classify captive portals as healthy (200/302 accepted as internet). The
bread-bus subscription thread also read/wrote config and state files
concurrently with the watch loop. Fix all of those plus: EDITOR values
with arguments, scan --to silently ignoring unknown profiles, deleted
core profiles being resurrected, inline-network migration data loss,
login never retried, XDG-unaware install-service, detect persisting a
stale default profile, password length leaking through the mask, a
stdin/stdout pipe deadlock, and several minor UI/robustness issues.
Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
This commit is contained in:
parent
02e96126e0
commit
c02360a873
12 changed files with 538 additions and 189 deletions
17
src/util.rs
17
src/util.rs
|
|
@ -139,13 +139,6 @@ fn spawn_run(prog: &str, args: &[&str], stdin: Option<&str>, timeout: Duration)
|
|||
Err(_) => return Output::failed(),
|
||||
};
|
||||
|
||||
if let Some(data) = stdin {
|
||||
if let Some(mut sink) = child.stdin.take() {
|
||||
let _ = sink.write_all(data.as_bytes());
|
||||
// Drop closes the pipe so the child's read sees EOF.
|
||||
}
|
||||
}
|
||||
|
||||
let mut stdout_pipe = child.stdout.take();
|
||||
let mut stderr_pipe = child.stderr.take();
|
||||
|
||||
|
|
@ -164,6 +157,16 @@ fn spawn_run(prog: &str, args: &[&str], stdin: Option<&str>, timeout: Duration)
|
|||
buf
|
||||
});
|
||||
|
||||
// Feed stdin only now that the reader threads are draining stdout and
|
||||
// stderr: a chatty child could otherwise fill its stdout pipe while we
|
||||
// block writing stdin, deadlocking both sides.
|
||||
if let Some(data) = stdin {
|
||||
if let Some(mut sink) = child.stdin.take() {
|
||||
let _ = sink.write_all(data.as_bytes());
|
||||
// Drop closes the pipe so the child's read sees EOF.
|
||||
}
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
let status = loop {
|
||||
match child.try_wait() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue