─── stop ──────────────────────────────────────────────────────
(args []string, logger *zap.Logger)
| 124 | // ─── stop ────────────────────────────────────────────────────── |
| 125 | |
| 126 | func daemonStop(args []string, logger *zap.Logger) error { |
| 127 | fs := flag.NewFlagSet("daemon stop", flag.ContinueOnError) |
| 128 | socket := fs.String("socket", "", "override socket path") |
| 129 | if err := fs.Parse(args); err != nil { |
| 130 | return err |
| 131 | } |
| 132 | cfg := scheduler.LoadConfigFromEnv() |
| 133 | if *socket != "" { |
| 134 | cfg.DaemonSocket = *socket |
| 135 | } |
| 136 | s := scheduler.DefaultSocketPath(cfg) |
| 137 | if err := scheduler.CheckDaemon(s); err != nil { |
| 138 | return fmt.Errorf("daemon: no reachable daemon at %s (%w)", s, err) |
| 139 | } |
| 140 | // We send SIGTERM to the PID referenced by <socket>.pid. |
| 141 | data, err := os.ReadFile(s + ".pid") // #nosec G304 -- daemon-scoped |
| 142 | if err != nil { |
| 143 | return fmt.Errorf("daemon: read pid file: %w", err) |
| 144 | } |
| 145 | pid, err := strconv.Atoi(strings.TrimSpace(string(data))) |
| 146 | if err != nil { |
| 147 | return fmt.Errorf("daemon: parse pid: %w", err) |
| 148 | } |
| 149 | proc, err := os.FindProcess(pid) |
| 150 | if err != nil { |
| 151 | return fmt.Errorf("daemon: find process: %w", err) |
| 152 | } |
| 153 | if err := proc.Signal(syscall.SIGTERM); err != nil { |
| 154 | return fmt.Errorf("daemon: send SIGTERM: %w", err) |
| 155 | } |
| 156 | // Wait for socket to disappear. |
| 157 | deadline := time.Now().Add(15 * time.Second) |
| 158 | for time.Now().Before(deadline) { |
| 159 | if scheduler.CheckDaemon(s) != nil { |
| 160 | _, _ = fmt.Fprintln(os.Stdout, "chatcli daemon stopped") |
| 161 | return nil |
| 162 | } |
| 163 | time.Sleep(200 * time.Millisecond) |
| 164 | } |
| 165 | logger.Warn("daemon did not exit within 15s; forcing SIGKILL") |
| 166 | _ = proc.Signal(syscall.SIGKILL) |
| 167 | return nil |
| 168 | } |
| 169 | |
| 170 | // ─── status / ping / install ────────────────────────────────── |
| 171 |
no test coverage detected