aboutsummaryrefslogtreecommitdiff
path: root/context/context.go
diff options
context:
space:
mode:
Diffstat (limited to 'context/context.go')
-rw-r--r--context/context.go27
1 files changed, 19 insertions, 8 deletions
diff --git a/context/context.go b/context/context.go
index 449ca32..60531fb 100644
--- a/context/context.go
+++ b/context/context.go
@@ -262,6 +262,19 @@ func parentCancelCtx(parent Context) (*cancelCtx, bool) {
}
}
+// removeChild removes a context from its parent.
+func removeChild(parent Context, child canceler) {
+ p, ok := parentCancelCtx(parent)
+ if !ok {
+ return
+ }
+ p.mu.Lock()
+ if p.children != nil {
+ delete(p.children, child)
+ }
+ p.mu.Unlock()
+}
+
// A canceler is a context type that can be canceled directly. The
// implementations are *cancelCtx and *timerCtx.
type canceler interface {
@@ -316,13 +329,7 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) {
c.mu.Unlock()
if removeFromParent {
- if p, ok := parentCancelCtx(c.Context); ok {
- p.mu.Lock()
- if p.children != nil {
- delete(p.children, c)
- }
- p.mu.Unlock()
- }
+ removeChild(c.Context, c)
}
}
@@ -380,7 +387,11 @@ func (c *timerCtx) String() string {
}
func (c *timerCtx) cancel(removeFromParent bool, err error) {
- c.cancelCtx.cancel(removeFromParent, err)
+ c.cancelCtx.cancel(false, err)
+ if removeFromParent {
+ // Remove this timerCtx from its parent cancelCtx's children.
+ removeChild(c.cancelCtx.Context, c)
+ }
c.mu.Lock()
if c.timer != nil {
c.timer.Stop()