fix: Windows daemon survives session jobs; quieter wrap note; correct mute error
Verified on a Windows 11 VM over WinRM: doctor, SAPI synthesis, Edge, oto/WASAPI playback, autostart, mute file, wrap exit codes, doctor --probe and toast mode all work. Three findings fixed: - The autostarted daemon died with the WinRM shell: Windows session hosts (WinRM, SSH, CI runners) put children into a job object that is terminated with the session. Spawn now starts the daemon with CREATE_BREAKAWAY_FROM_JOB first and falls back to a start without it when the job forbids breakaway. Confirmed: the daemon now outlives the WinRM shell and `talk daemon stop` still ends it. - `talk mute` without a daemon printed "daemon call failed (<nil>)": the outer err was reported instead of the call's. Now "no daemon (<reason>); writing the mute file directly". - `talk wrap` printed "command did not exit cleanly" for every non-zero exit code. The note is now reserved for commands that produced no exit code of their own (not found, signal); a plain failure is carried by the announcement and the exit code alone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
85fa64cfe6
commit
1b971bc3f6
7 files changed
+52
-22
No files matched your search
@@ -17,7 +17,6 @@ import (
|
||||
// port in use) without waiting for a timeout. If the caller exits first,
|
||||
// the daemon keeps running (that is the point).
|
||||
func Spawn(exe, logPath string, env []string) (<-chan error, error) {
|
||||
var logFile *os.File
|
||||
if logPath == "" {
|
||||
logPath = os.DevNull
|
||||
}
|
||||
@@ -27,13 +26,24 @@ func Spawn(exe, logPath string, env []string) (<-chan error, error) {
|
||||
}
|
||||
defer logFile.Close() // the child holds its own handle
|
||||
|
||||
cmd := exec.Command(exe, "daemon", "run")
|
||||
cmd.Env = env
|
||||
cmd.Stdin = nil
|
||||
cmd.Stdout = logFile
|
||||
cmd.Stderr = logFile
|
||||
detach(cmd)
|
||||
if err := cmd.Start(); err != nil {
|
||||
// First attempt: fully detached, including a breakaway from the parent's
|
||||
// job object (Windows). Shells such as WinRM, SSH servers or CI runners
|
||||
// put children into a job that is terminated with the session; the
|
||||
// breakaway lets the daemon outlive it. If the job forbids breakaway,
|
||||
// CreateProcess fails, and the second attempt starts without it.
|
||||
var cmd *exec.Cmd
|
||||
for _, breakaway := range []bool{true, false} {
|
||||
cmd = exec.Command(exe, "daemon", "run")
|
||||
cmd.Env = env
|
||||
cmd.Stdin = nil
|
||||
cmd.Stdout = logFile
|
||||
cmd.Stderr = logFile
|
||||
detach(cmd, breakaway)
|
||||
if err = cmd.Start(); err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("starting daemon (%s daemon run): %w", exe, err)
|
||||
}
|
||||
exited := make(chan error, 1)
|
||||
|
||||
Reference in new issue
Block a user