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 <gusted@noreply.codeberg.org>
Co-authored-by: nachtjasmin <nachtjasmin@posteo.de>
Co-committed-by: nachtjasmin <nachtjasmin@posteo.de>
This commit is contained in:
nachtjasmin 2026-03-04 00:45:38 +01:00 committed by Gusted
parent 8d6812df25
commit b21193ee50
2 changed files with 42 additions and 19 deletions

View file

@ -1,4 +1,5 @@
// Copyright 2018 The Gitea Authors. All rights reserved. // Copyright 2018 The Gitea Authors. All rights reserved.
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Package cmd provides subcommands to the gitea binary - such as "web" or // 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 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) { func installSignals(ctx context.Context) (context.Context, context.CancelFunc) {
ctx, cancel := context.WithCancel(ctx) return signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
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
} }
func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) { func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) {

39
cmd/cmd_test.go Normal file
View file

@ -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")
}
})
}
}