From 8cad37466f68a9bddf546b0a133af2d966655a7e Mon Sep 17 00:00:00 2001 From: bufdev Date: Thu, 10 Oct 2024 11:23:11 -0400 Subject: [PATCH 1/3] Cleanup interrupt even further --- private/pkg/app/app.go | 7 +---- private/pkg/interrupt/interrupt.go | 38 +++++++++++++++++++----- private/pkg/interrupt/interrupt_other.go | 9 +++--- private/pkg/interrupt/interrupt_unix.go | 9 +++--- 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/private/pkg/app/app.go b/private/pkg/app/app.go index 0f9011de1d..866fe7d61c 100644 --- a/private/pkg/app/app.go +++ b/private/pkg/app/app.go @@ -326,12 +326,7 @@ func Main(ctx context.Context, f func(context.Context, Container) error) { // The run will be stopped on interrupt signal. // The exit code can be determined using GetExitCode. func Run(ctx context.Context, container Container, f func(context.Context, Container) error) error { - ctx, cancel := interrupt.NotifyContext(ctx) - go func() { - <-ctx.Done() - cancel() - }() - if err := f(ctx, container); err != nil { + if err := f(interrupt.Handle(ctx), container); err != nil { printError(container, err) return err } diff --git a/private/pkg/interrupt/interrupt.go b/private/pkg/interrupt/interrupt.go index 50f04e1496..446e5bc6f0 100644 --- a/private/pkg/interrupt/interrupt.go +++ b/private/pkg/interrupt/interrupt.go @@ -16,14 +16,38 @@ package interrupt import ( "context" - "os" "os/signal" ) -var interruptSignals = append([]os.Signal{os.Interrupt}, extraSignals...) - -// NotifyContext returns a new [context.Context] from [signal.NotifyContext] -// with the appropriate interrupt signals. -func NotifyContext(ctx context.Context) (context.Context, context.CancelFunc) { - return signal.NotifyContext(ctx, interruptSignals...) +// Handle returns a copy of the parent [context.Context] that is marked done +// when an interrupt signal arrives or when the parent Context's Done channel +// is closed, whichever happens first. +// +// Signal handling is unregistered automatically by this function when the +// first interrupt signal arrives, which will restore the default interrupt +// signal behabior of Go programs (to exit). +// +// In effect, this function is functionally equivalent to: +// +// ctx, cancel := signal.NotifyContext(ctx, interrupt.Signals...) +// defer func() { +// <-ctx.Done() +// cancel() +// }() +// +// Most programs should wrap their contexts using this function to enable interrupt +// signal handling. The first interrupt signal will result in the context's Done +// channel closing. The second interrupt signal will result in the program exiting. +// +// func main() { +// ctx := interrupt.Handle(context.Background()) +// ... +// } +func Handle(ctx context.Context) context.Context { + ctx, cancel := signal.NotifyContext(ctx, Signals...) + defer func() { + <-ctx.Done() + cancel() + }() + return ctx } diff --git a/private/pkg/interrupt/interrupt_other.go b/private/pkg/interrupt/interrupt_other.go index 5a5dd97924..8e3e48a846 100644 --- a/private/pkg/interrupt/interrupt_other.go +++ b/private/pkg/interrupt/interrupt_other.go @@ -18,9 +18,8 @@ package interrupt import "os" -// extraSignals are signals beyond os.Interrupt that we want to be handled -// as interrupts. +// Signals are all interrupt signals. // -// For unix-like platforms, this adds syscall.SIGTERM. No other signals -// are added for other platforms. -var extraSignals = []os.Signal{} +// As opposed to os.Interrupt, this adds syscall.SIGTERM for unix-like platforms. For +// other platforms, this is just os.Interrupt +var Signals = []os.Signal{os.Interrupt} diff --git a/private/pkg/interrupt/interrupt_unix.go b/private/pkg/interrupt/interrupt_unix.go index 903ca1ddc7..3b476ce5cf 100644 --- a/private/pkg/interrupt/interrupt_unix.go +++ b/private/pkg/interrupt/interrupt_unix.go @@ -21,9 +21,8 @@ import ( "syscall" ) -// extraSignals are signals beyond os.Interrupt that we want to be handled -// as interrupts. +// Signals are all interrupt signals. // -// For unix-like platforms, this adds syscall.SIGTERM. No other signals -// are added for other platforms. -var extraSignals = []os.Signal{syscall.SIGTERM} +// As opposed to os.Interrupt, this adds syscall.SIGTERM for unix-like platforms. For +// other platforms, this is just os.Interrupt +var Signals = []os.Signal{os.Interrupt, syscall.SIGTERM} From de7c71fc28369dbbcb7fec50778c3998fca4c9ee Mon Sep 17 00:00:00 2001 From: bufdev Date: Thu, 10 Oct 2024 12:00:13 -0400 Subject: [PATCH 2/3] fix --- private/pkg/interrupt/interrupt.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/private/pkg/interrupt/interrupt.go b/private/pkg/interrupt/interrupt.go index 446e5bc6f0..7ba819b04f 100644 --- a/private/pkg/interrupt/interrupt.go +++ b/private/pkg/interrupt/interrupt.go @@ -30,7 +30,7 @@ import ( // In effect, this function is functionally equivalent to: // // ctx, cancel := signal.NotifyContext(ctx, interrupt.Signals...) -// defer func() { +// go func() { // <-ctx.Done() // cancel() // }() @@ -45,7 +45,7 @@ import ( // } func Handle(ctx context.Context) context.Context { ctx, cancel := signal.NotifyContext(ctx, Signals...) - defer func() { + go func() { <-ctx.Done() cancel() }() From 83cc0be40a4b204b3c98b5f4673ec42c12044f55 Mon Sep 17 00:00:00 2001 From: bufdev Date: Thu, 10 Oct 2024 13:01:25 -0400 Subject: [PATCH 3/3] commit --- private/pkg/interrupt/interrupt.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/private/pkg/interrupt/interrupt.go b/private/pkg/interrupt/interrupt.go index 7ba819b04f..cce88d933f 100644 --- a/private/pkg/interrupt/interrupt.go +++ b/private/pkg/interrupt/interrupt.go @@ -25,7 +25,7 @@ import ( // // Signal handling is unregistered automatically by this function when the // first interrupt signal arrives, which will restore the default interrupt -// signal behabior of Go programs (to exit). +// signal behavior of Go programs (to exit). // // In effect, this function is functionally equivalent to: //