Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PACKAGES ?= mountinfo mount sequential signal symlink
PACKAGES ?= appcontext mountinfo mount sequential signal symlink
BINDIR ?= _build/bin
CROSS ?= linux/arm linux/arm64 linux/ppc64le linux/s390x \
freebsd/amd64 openbsd/amd64 darwin/amd64 darwin/arm64 windows/amd64
Expand Down
45 changes: 45 additions & 0 deletions appcontext/appcontext.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package appcontext

import (
"context"
"os"
"os/signal"
"sync"
)

var (
appContextCache context.Context
appContextOnce sync.Once
)

// Context returns a static context that reacts to termination signals of the
// running process. Useful in CLI tools.
func Context() context.Context {
appContextOnce.Do(func() {
signals := make(chan os.Signal, 2048)
signal.Notify(signals, terminationSignals...)

const exitLimit = 3
retries := 0

ctx := context.Background()
for _, f := range inits {
ctx = f(ctx)
}

ctx, cancel := context.WithCancel(ctx)
appContextCache = ctx

go func() {
for {
<-signals
cancel()
retries++
if retries >= exitLimit {
os.Exit(1)
}
}
}()
})
return appContextCache
}
12 changes: 12 additions & 0 deletions appcontext/appcontext_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//go:build !windows
// +build !windows

package appcontext

import (
"os"

"golang.org/x/sys/unix"
)

var terminationSignals = []os.Signal{unix.SIGTERM, unix.SIGINT}
7 changes: 7 additions & 0 deletions appcontext/appcontext_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package appcontext

import (
"os"
)

var terminationSignals = []os.Signal{os.Interrupt}
5 changes: 5 additions & 0 deletions appcontext/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/moby/sys/appcontext

go 1.17

require golang.org/x/sys v0.11.0
2 changes: 2 additions & 0 deletions appcontext/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
14 changes: 14 additions & 0 deletions appcontext/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package appcontext

import (
"context"
)

type Initializer func(context.Context) context.Context

var inits []Initializer

// Register stores a new context initializer that runs on app context creation
func Register(f Initializer) {
inits = append(inits, f)
}