Skip to content

Commit

Permalink
Merge branch 'caddyserver:master' into make-trusted-leaf-certs-pluggable
Browse files Browse the repository at this point in the history
  • Loading branch information
armadi1809 authored Mar 3, 2024
2 parents ea2a7fd + 8f82047 commit 5acc7bf
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
check-latest: true

- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v4
with:
version: v1.55

Expand Down
28 changes: 28 additions & 0 deletions caddy.go
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,7 @@ func exitProcess(ctx context.Context, logger *zap.Logger) {
logger.Warn("exiting; byeee!! 👋")

exitCode := ExitCodeSuccess
lastContext := ActiveContext()

// stop all apps
if err := Stop(); err != nil {
Expand All @@ -736,6 +737,16 @@ func exitProcess(ctx context.Context, logger *zap.Logger) {
}
}

// execute any process-exit callbacks
for _, exitFunc := range lastContext.exitFuncs {
exitFunc(ctx)
}
exitFuncsMu.Lock()
for _, exitFunc := range exitFuncs {
exitFunc(ctx)
}
exitFuncsMu.Unlock()

// shut down admin endpoint(s) in goroutines so that
// if this function was called from an admin handler,
// it has a chance to return gracefully
Expand Down Expand Up @@ -774,6 +785,23 @@ var exiting = new(int32) // accessed atomically
// EXPERIMENTAL API: subject to change or removal.
func Exiting() bool { return atomic.LoadInt32(exiting) == 1 }

// OnExit registers a callback to invoke during process exit.
// This registration is PROCESS-GLOBAL, meaning that each
// function should only be registered once forever, NOT once
// per config load (etc).
//
// EXPERIMENTAL API: subject to change or removal.
func OnExit(f func(context.Context)) {
exitFuncsMu.Lock()
exitFuncs = append(exitFuncs, f)
exitFuncsMu.Unlock()
}

var (
exitFuncs []func(context.Context)
exitFuncsMu sync.Mutex
)

// Duration can be an integer or a string. An integer is
// interpreted as nanoseconds. If a string, it is a Go
// time.Duration value such as `300ms`, `1.5h`, or `2h45m`;
Expand Down
2 changes: 1 addition & 1 deletion cmd/cobra.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func onlyVersionText() string {

func caddyCmdToCobra(caddyCmd Command) *cobra.Command {
cmd := &cobra.Command{
Use: caddyCmd.Name,
Use: caddyCmd.Name + " " + caddyCmd.Usage,
Short: caddyCmd.Short,
Long: caddyCmd.Long,
}
Expand Down
15 changes: 13 additions & 2 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ type Context struct {

moduleInstances map[string][]Module
cfg *Config
cleanupFuncs []func()
ancestry []Module
cleanupFuncs []func() // invoked at every config unload
exitFuncs []func(context.Context) // invoked at config unload ONLY IF the process is exiting (EXPERIMENTAL)
}

// NewContext provides a new context derived from the given
Expand Down Expand Up @@ -86,7 +87,8 @@ func (ctx *Context) OnCancel(f func()) {
ctx.cleanupFuncs = append(ctx.cleanupFuncs, f)
}

// Filesystems returns a ref to the FilesystemMap
// Filesystems returns a ref to the FilesystemMap.
// EXPERIMENTAL: This API is subject to change.
func (ctx *Context) Filesystems() FileSystems {
// if no config is loaded, we use a default filesystemmap, which includes the osfs
if ctx.cfg == nil {
Expand All @@ -95,6 +97,15 @@ func (ctx *Context) Filesystems() FileSystems {
return ctx.cfg.filesystems
}

// OnExit executes f when the process exits gracefully.
// The function is only executed if the process is gracefully
// shut down while this context is active.
//
// EXPERIMENTAL API: subject to change or removal.
func (ctx *Context) OnExit(f func(context.Context)) {
ctx.exitFuncs = append(ctx.exitFuncs, f)
}

// LoadModule loads the Caddy module(s) from the specified field of the parent struct
// pointer and returns the loaded module(s). The struct pointer and its field name as
// a string are necessary so that reflection can be used to read the struct tag on the
Expand Down

0 comments on commit 5acc7bf

Please sign in to comment.