master
go 31 lines 927 Bytes
Raw
1 package shutdown
2
3 import (
4 "context"
5 "fmt"
6 "time"
7
8 logging "github.com/ipfs/go-log/v2"
9 )
10
11 var closeLog = logging.Logger("shutdown")
12
13 // CloseWithCtx runs close in a goroutine and returns when it finishes or
14 // when ctx is done, whichever comes first. If ctx fires before close
15 // returns, the goroutine is leaked intentionally; the process is about to
16 // exit, so the leak is bounded by process lifetime. Logs at ERROR which
17 // subsystem failed to close in time so operators see it in journal/docker
18 // logs.
19 func CloseWithCtx(ctx context.Context, name string, close func() error) error {
20 done := make(chan error, 1)
21 start := time.Now()
22 go func() { done <- close() }()
23 select {
24 case err := <-done:
25 return err
26 case <-ctx.Done():
27 closeLog.Errorf("subsystem %q failed to close within shutdown deadline (after %s): %s",
28 name, time.Since(start), ctx.Err())
29 return fmt.Errorf("%s close: %w", name, ctx.Err())
30 }
31 }