Skip to content

Commit cf8d402

Browse files
authored
feat(agent): Handle signals and shutdown gracefully (#5914)
This change allows the agent to handle common shutdown signals like interrupt, hangup and terminate and initiate a graceful shutdown. As long as terraform providers initiate graceful shutdowns via the aforementioned signals, things like SSH connections will be closed immediately on shutdown instead of being left hanging/timing out due to the agent being abruptly killed. Refs: #4677, #5901
1 parent 91ef8d9 commit cf8d402

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

cli/agent.go

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http/pprof"
88
"net/url"
99
"os"
10+
"os/signal"
1011
"path/filepath"
1112
"runtime"
1213
"time"
@@ -35,12 +36,10 @@ func workspaceAgent() *cobra.Command {
3536
Use: "agent",
3637
// This command isn't useful to manually execute.
3738
Hidden: true,
38-
RunE: func(cmd *cobra.Command, args []string) error {
39+
RunE: func(cmd *cobra.Command, _ []string) error {
3940
ctx, cancel := context.WithCancel(cmd.Context())
4041
defer cancel()
4142

42-
go dumpHandler(ctx)
43-
4443
rawURL, err := cmd.Flags().GetString(varAgentURL)
4544
if err != nil {
4645
return xerrors.Errorf("CODER_AGENT_URL must be set: %w", err)
@@ -50,18 +49,18 @@ func workspaceAgent() *cobra.Command {
5049
return xerrors.Errorf("parse %q: %w", rawURL, err)
5150
}
5251

53-
logWriter := &lumberjack.Logger{
54-
Filename: filepath.Join(os.TempDir(), "coder-agent.log"),
55-
MaxSize: 5, // MB
56-
}
57-
defer logWriter.Close()
58-
logger := slog.Make(sloghuman.Sink(cmd.ErrOrStderr()), sloghuman.Sink(logWriter)).Leveled(slog.LevelDebug)
59-
6052
isLinux := runtime.GOOS == "linux"
6153

6254
// Spawn a reaper so that we don't accumulate a ton
6355
// of zombie processes.
6456
if reaper.IsInitProcess() && !noReap && isLinux {
57+
logWriter := &lumberjack.Logger{
58+
Filename: filepath.Join(os.TempDir(), "coder-agent-init.log"),
59+
MaxSize: 5, // MB
60+
}
61+
defer logWriter.Close()
62+
logger := slog.Make(sloghuman.Sink(cmd.ErrOrStderr()), sloghuman.Sink(logWriter)).Leveled(slog.LevelDebug)
63+
6564
logger.Info(ctx, "spawning reaper process")
6665
// Do not start a reaper on the child process. It's important
6766
// to do this else we fork bomb ourselves.
@@ -76,6 +75,28 @@ func workspaceAgent() *cobra.Command {
7675
return nil
7776
}
7877

78+
// Handle interrupt signals to allow for graceful shutdown,
79+
// note that calling stopNotify disables the signal handler
80+
// and the next interrupt will terminate the program (you
81+
// probably want cancel instead).
82+
//
83+
// Note that we don't want to handle these signals in the
84+
// process that runs as PID 1, that's why we do this after
85+
// the reaper forked.
86+
ctx, stopNotify := signal.NotifyContext(ctx, InterruptSignals...)
87+
defer stopNotify()
88+
89+
// dumpHandler does signal handling, so we call it after the
90+
// reaper.
91+
go dumpHandler(ctx)
92+
93+
logWriter := &lumberjack.Logger{
94+
Filename: filepath.Join(os.TempDir(), "coder-agent.log"),
95+
MaxSize: 5, // MB
96+
}
97+
defer logWriter.Close()
98+
logger := slog.Make(sloghuman.Sink(cmd.ErrOrStderr()), sloghuman.Sink(logWriter)).Leveled(slog.LevelDebug)
99+
79100
version := buildinfo.Version()
80101
logger.Info(ctx, "starting agent",
81102
slog.F("url", coderURL),

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy