sketch: add -ignoresig flag to ignore SIGINT and SIGTERM
Inside the container, do not let the agent kill PID 1.
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s5197e5ad119cd474k
diff --git a/cmd/sketch/main.go b/cmd/sketch/main.go
index ef06e49..d56fe7a 100644
--- a/cmd/sketch/main.go
+++ b/cmd/sketch/main.go
@@ -12,10 +12,12 @@
"net/http"
"os"
"os/exec"
+ "os/signal"
"path/filepath"
"runtime"
"runtime/debug"
"strings"
+ "syscall"
"sketch.dev/experiment"
"sketch.dev/llm"
@@ -50,6 +52,11 @@
func run() error {
flagArgs := parseCLIFlags()
+ // Set up signal handling if -ignoresig flag is set
+ if flagArgs.ignoreSig {
+ setupSignalIgnoring()
+ }
+
if flagArgs.version {
bi, ok := debug.ReadBuildInfo()
if ok {
@@ -196,6 +203,7 @@
sshPort int
forceRebuild bool
linkToGitHub bool
+ ignoreSig bool
gitUsername string
gitEmail string
@@ -251,6 +259,7 @@
userFlags.Var(&flags.mounts, "mount", "volume to mount in the container in format /path/on/host:/path/in/container (can be repeated)")
userFlags.BoolVar(&flags.termUI, "termui", true, "enable terminal UI")
userFlags.StringVar(&flags.branchPrefix, "branch-prefix", "sketch/", "prefix for git branches created by sketch")
+ userFlags.BoolVar(&flags.ignoreSig, "ignoresig", false, "ignore typical termination signals (SIGINT, SIGTERM)")
userFlags.Var(&flags.mcpServers, "mcp", "MCP server configuration as JSON (can be repeated). Schema: {\"name\": \"server-name\", \"type\": \"stdio|http|sse\", \"url\": \"...\", \"command\": \"...\", \"args\": [...], \"env\": {...}, \"headers\": {...}}")
// Internal flags (for sketch developers or internal use)
@@ -834,3 +843,25 @@
fmt.Printf("Successfully dumped embedded /dist/ filesystem to %q\n", outputDir)
return nil
}
+
+// setupSignalIgnoring sets up signal handling to ignore SIGINT and SIGTERM
+// when the -ignoresig flag is used. This prevents the typical Ctrl+C or
+// termination signals from killing the process.
+func setupSignalIgnoring() {
+ // Create a channel to receive signals
+ sigChan := make(chan os.Signal, 1)
+
+ // Register the channel to receive specific signals
+ // We ignore SIGINT (Ctrl+C) and SIGTERM (termination request)
+ // but allow SIGQUIT to still work for debugging/stack dumps
+ signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
+
+ // Start a goroutine to handle the signals
+ go func() {
+ for sig := range sigChan {
+ // Simply ignore the signal by doing nothing
+ // This prevents the default behavior of terminating the process
+ _ = sig // Suppress unused variable warning
+ }
+ }()
+}