Skip to content

Commit 6a0f8ae

Browse files
authored
fix: Add SIGHUP and SIGTERM handling to coder server (#3543)
* fix: Add `SIGHUP` and `SIGTERM` handling to `coder server` To prevent additional signals from aborting program execution, signal handling was moved to the beginning of the main function, this ensures that signals stays registered for the entire shutdown procedure. Fixes #1529
1 parent 380022f commit 6a0f8ae

File tree

3 files changed

+38
-11
lines changed

3 files changed

+38
-11
lines changed

cli/server.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,19 @@ func server() *cobra.Command {
127127
ctx, cancel := context.WithCancel(cmd.Context())
128128
defer cancel()
129129

130+
// Register signals early on so that graceful shutdown can't
131+
// be interrupted by additional signals. Note that we avoid
132+
// shadowing cancel() (from above) here because notifyStop()
133+
// restores default behavior for the signals. This protects
134+
// the shutdown sequence from abrubtly terminating things
135+
// like: database migrations, provisioner work, workspace
136+
// cleanup in dev-mode, etc.
137+
//
138+
// To get out of a graceful shutdown, the user can send
139+
// SIGQUIT with ctrl+\ or SIGKILL with `kill -9`.
140+
notifyCtx, notifyStop := signal.NotifyContext(ctx, interruptSignals...)
141+
defer notifyStop()
142+
130143
// Clean up idle connections at the end, e.g.
131144
// embedded-postgres can leave an idle connection
132145
// which is caught by goleaks.
@@ -521,22 +534,13 @@ func server() *cobra.Command {
521534
// such as via the systemd service.
522535
_ = config.URL().Write(client.URL.String())
523536

524-
// Because the graceful shutdown includes cleaning up workspaces in dev mode, we're
525-
// going to make it harder to accidentally skip the graceful shutdown by hitting ctrl+c
526-
// two or more times. So the stopChan is unlimited in size and we don't call
527-
// signal.Stop() until graceful shutdown finished--this means we swallow additional
528-
// SIGINT after the first. To get out of a graceful shutdown, the user can send SIGQUIT
529-
// with ctrl+\ or SIGTERM with `kill`.
530-
ctx, stop := signal.NotifyContext(ctx, os.Interrupt)
531-
defer stop()
532-
533537
// Currently there is no way to ask the server to shut
534538
// itself down, so any exit signal will result in a non-zero
535539
// exit of the server.
536540
var exitErr error
537541
select {
538-
case <-ctx.Done():
539-
exitErr = ctx.Err()
542+
case <-notifyCtx.Done():
543+
exitErr = notifyCtx.Err()
540544
_, _ = fmt.Fprintln(cmd.OutOrStdout(), cliui.Styles.Bold.Render(
541545
"Interrupt caught, gracefully exiting. Use ctrl+\\ to force quit",
542546
))

cli/signal_unix.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//go:build !windows
2+
3+
package cli
4+
5+
import (
6+
"os"
7+
"syscall"
8+
)
9+
10+
var interruptSignals = []os.Signal{
11+
os.Interrupt,
12+
syscall.SIGTERM,
13+
syscall.SIGHUP,
14+
}

cli/signal_windows.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//go:build windows
2+
3+
package cli
4+
5+
import (
6+
"os"
7+
)
8+
9+
var interruptSignals = []os.Signal{os.Interrupt}

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