Fix CampusNAS recovery after VPN loss
This commit is contained in:
@@ -15,6 +15,19 @@ private final class ResumeOnce: @unchecked Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
/// `Process.terminate()` only sends SIGTERM. A wedged network client (notably
|
||||
/// `smbutil` after a tunnel disappears) may ignore it and keep the pipe open,
|
||||
/// leaving the reader thread in `readDataToEndOfFile()` forever. Escalate to
|
||||
/// SIGKILL after a short grace period so every probe is actually bounded.
|
||||
private func stop(_ process: Process) {
|
||||
guard process.isRunning else { return }
|
||||
process.terminate()
|
||||
let pid = process.processIdentifier
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
|
||||
if process.isRunning { Darwin.kill(pid, SIGKILL) }
|
||||
}
|
||||
}
|
||||
|
||||
enum Probe {
|
||||
/// Runs a command and reports whether it exited 0. A process that outlives
|
||||
/// `timeout` is killed and treated as failure — the VPN wrapper can block on
|
||||
@@ -51,7 +64,7 @@ enum Probe {
|
||||
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + timeout) {
|
||||
guard process.isRunning else { return }
|
||||
process.terminate()
|
||||
stop(process)
|
||||
if once.claim() { continuation.resume(returning: false) }
|
||||
}
|
||||
}
|
||||
@@ -119,7 +132,7 @@ enum Probe {
|
||||
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + timeout) {
|
||||
guard process.isRunning else { return }
|
||||
process.terminate()
|
||||
stop(process)
|
||||
if once.claim() {
|
||||
continuation.resume(returning: RunResult(
|
||||
ok: false, output: "", error: "timeout after \(timeout)s"))
|
||||
@@ -170,7 +183,7 @@ enum Probe {
|
||||
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + timeout) {
|
||||
guard process.isRunning else { return }
|
||||
process.terminate()
|
||||
stop(process)
|
||||
if once.claim() { continuation.resume(returning: nil) }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user