// Copyright (c) 2026 Winlin // // SPDX-License-Identifier: MIT package signal import ( "context" "os" "os/signal" "syscall" "time" "srsx/internal/env" "srsx/internal/errors" "srsx/internal/logger" ) // Indirections so tests can substitute signal delivery and process exit. var ( signalNotify = signal.Notify osExit = os.Exit ) func InstallSignals(ctx context.Context, cancel context.CancelFunc) { sc := make(chan os.Signal, 1) signalNotify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) go func() { for s := range sc { logger.Debug(ctx, "Got signal %v", s) cancel() } }() } func InstallForceQuit(ctx context.Context, environment env.ProxyEnvironment) error { var forceTimeout time.Duration timeoutStr := environment.ForceQuitTimeout() if t, err := time.ParseDuration(timeoutStr); err != nil { return errors.Wrapf(err, "parse force timeout %v", timeoutStr) } else { forceTimeout = t } go func() { <-ctx.Done() time.Sleep(forceTimeout) logger.Warn(ctx, "Force to exit by timeout") osExit(1) }() return nil }