From b21193ee5035892da2f64e2ecb94e27c2ef44974 Mon Sep 17 00:00:00 2001 From: nachtjasmin Date: Wed, 4 Mar 2026 00:45:38 +0100 Subject: [PATCH] chore: use `signal.NotifyContext` over custom implementation (#10311) Go 1.16 added the signal.NotifyContext helper utility. `installSignals` could be further inlined in a future iteration, if needed. When reading the [function documentation](https://pkg.go.dev/os/signal#NotifyContext), it becomes clear that this is doing the exact same thing as the old code. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10311 Reviewed-by: Gusted Co-authored-by: nachtjasmin Co-committed-by: nachtjasmin --- cmd/cmd.go | 22 +++------------------- cmd/cmd_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 cmd/cmd_test.go diff --git a/cmd/cmd.go b/cmd/cmd.go index 379609d294..a6e5d8fcfe 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,4 +1,5 @@ // Copyright 2018 The Gitea Authors. All rights reserved. +// Copyright 2026 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT // Package cmd provides subcommands to the gitea binary - such as "web" or @@ -89,26 +90,9 @@ If this is the intended configuration file complete the [database] section.`, se return nil } +// installSignals returns a context that's cancelled on the SIGINT and SIGTERM signals or if the passed ctx is cancelled. func installSignals(ctx context.Context) (context.Context, context.CancelFunc) { - ctx, cancel := context.WithCancel(ctx) - go func() { - // install notify - signalChannel := make(chan os.Signal, 1) - - signal.Notify( - signalChannel, - syscall.SIGINT, - syscall.SIGTERM, - ) - select { - case <-signalChannel: - case <-ctx.Done(): - } - cancel() - signal.Reset() - }() - - return ctx, cancel + return signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM) } func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) { diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go new file mode 100644 index 0000000000..8e66cbdba1 --- /dev/null +++ b/cmd/cmd_test.go @@ -0,0 +1,39 @@ +// Copyright 2026 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT +package cmd + +import ( + "context" + "fmt" + "runtime" + "syscall" + "testing" + "time" +) + +func Test_installSignals(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skipf("Windows does not terminate in an awaitable manner") + return + } + + for _, s := range []syscall.Signal{syscall.SIGTERM, syscall.SIGINT} { + t.Run(fmt.Sprintf("Context is terminated on %s", s), func(t *testing.T) { + // Register the signal handler. context.Background() is chosen deliberately, + // because unlike t.Context(), we can be sure that it's not cancelled by a + // different handler. + ctx, cancel := installSignals(context.Background()) + t.Cleanup(cancel) + + // Send the signal in the background. + go syscall.Kill(syscall.Getpid(), s) + + select { + case <-time.Tick(time.Second * 10): + t.Fatalf("Context not cancelled via signal after 10 seconds") + case <-ctx.Done(): + t.Logf("Context was cancelled") + } + }) + } +}