check / check (push) Failing after 3s
SIGINT, SIGTERM and SIGHUP were caught for the whole run, but only the ssh and sftp children acted on them: the mnemonic prompt waited for Enter, and an interrupted `age encrypt -o` put the encryption of the cut-off input in place. Now they end the tool at once, except where a command cleans up first: `ssh to` and `ssh install` while ssh or sftp runs, and `age encrypt -o` and `age decrypt -o` while they write, where a signal up to a tenth of a second after the input ends still removes the unfinished file and exits 1. Those commands catch only the signals the tool was not started ignoring, so a run under nohup survives a hangup. Model: opus-5-5
35 lines
1.0 KiB
Go
35 lines
1.0 KiB
Go
// Package signals catches the signals that end the tool, for the
|
|
// commands that clean up before they end.
|
|
package signals
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
)
|
|
|
|
// Context is signal.NotifyContext for SIGINT, SIGTERM and SIGHUP: the
|
|
// context it returns is cancelled when one of them arrives, and stop
|
|
// stops catching them. It leaves out any of the three the tool was
|
|
// started with set to be ignored, as nohup does with SIGHUP, because
|
|
// catching a signal turns an ignored one back on and would end a run
|
|
// that was meant to survive it.
|
|
func Context(parent context.Context) (context.Context, context.CancelFunc) {
|
|
endings := []os.Signal{syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP}
|
|
caught := make([]os.Signal, 0, len(endings))
|
|
|
|
for _, ending := range endings {
|
|
if !signal.Ignored(ending) {
|
|
caught = append(caught, ending)
|
|
}
|
|
}
|
|
|
|
// Given no signals at all, NotifyContext would catch every one.
|
|
if len(caught) == 0 {
|
|
return context.WithCancel(parent)
|
|
}
|
|
|
|
return signal.NotifyContext(parent, caught...)
|
|
}
|