Source file src/context/context.go
1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package context defines the Context type, which carries deadlines, 6 // cancellation signals, and other request-scoped values across API boundaries 7 // and between processes. 8 // 9 // Incoming requests to a server should create a Context, and outgoing 10 // calls to servers should accept a Context. The chain of function 11 // calls between them must propagate the Context, optionally replacing 12 // it with a derived Context created using WithCancel, WithDeadline, 13 // WithTimeout, or WithValue. When a Context is canceled, all 14 // Contexts derived from it are also canceled. 15 // 16 // The WithCancel, WithDeadline, and WithTimeout functions take a 17 // Context (the parent) and return a derived Context (the child) and a 18 // CancelFunc. Calling the CancelFunc cancels the child and its 19 // children, removes the parent's reference to the child, and stops 20 // any associated timers. Failing to call the CancelFunc leaks the 21 // child and its children until the parent is canceled or the timer 22 // fires. The go vet tool checks that CancelFuncs are used on all 23 // control-flow paths. 24 // 25 // The WithCancelCause function returns a CancelCauseFunc, which 26 // takes an error and records it as the cancellation cause. Calling 27 // Cause on the canceled context or any of its children retrieves 28 // the cause. If no cause is specified, Cause(ctx) returns the same 29 // value as ctx.Err(). 30 // 31 // Programs that use Contexts should follow these rules to keep interfaces 32 // consistent across packages and enable static analysis tools to check context 33 // propagation: 34 // 35 // Do not store Contexts inside a struct type; instead, pass a Context 36 // explicitly to each function that needs it. The Context should be the first 37 // parameter, typically named ctx: 38 // 39 // func DoSomething(ctx context.Context, arg Arg) error { 40 // // ... use ctx ... 41 // } 42 // 43 // Do not pass a nil Context, even if a function permits it. Pass context.TODO 44 // if you are unsure about which Context to use. 45 // 46 // Use context Values only for request-scoped data that transits processes and 47 // APIs, not for passing optional parameters to functions. 48 // 49 // The same Context may be passed to functions running in different goroutines; 50 // Contexts are safe for simultaneous use by multiple goroutines. 51 // 52 // See https://blog.golang.org/context for example code for a server that uses 53 // Contexts. 54 package context 55 56 import ( 57 "errors" 58 "internal/reflectlite" 59 "sync" 60 "sync/atomic" 61 "time" 62 ) 63 64 // A Context carries a deadline, a cancellation signal, and other values across 65 // API boundaries. 66 // 67 // Context's methods may be called by multiple goroutines simultaneously. 68 type Context interface { 69 // Deadline returns the time when work done on behalf of this context 70 // should be canceled. Deadline returns ok==false when no deadline is 71 // set. Successive calls to Deadline return the same results. 72 Deadline() (deadline time.Time, ok bool) 73 74 // Done returns a channel that's closed when work done on behalf of this 75 // context should be canceled. Done may return nil if this context can 76 // never be canceled. Successive calls to Done return the same value. 77 // The close of the Done channel may happen asynchronously, 78 // after the cancel function returns. 79 // 80 // WithCancel arranges for Done to be closed when cancel is called; 81 // WithDeadline arranges for Done to be closed when the deadline 82 // expires; WithTimeout arranges for Done to be closed when the timeout 83 // elapses. 84 // 85 // Done is provided for use in select statements: 86 // 87 // // Stream generates values with DoSomething and sends them to out 88 // // until DoSomething returns an error or ctx.Done is closed. 89 // func Stream(ctx context.Context, out chan<- Value) error { 90 // for { 91 // v, err := DoSomething(ctx) 92 // if err != nil { 93 // return err 94 // } 95 // select { 96 // case <-ctx.Done(): 97 // return ctx.Err() 98 // case out <- v: 99 // } 100 // } 101 // } 102 // 103 // See https://blog.golang.org/pipelines for more examples of how to use 104 // a Done channel for cancellation. 105 Done() <-chan struct{} 106 107 // If Done is not yet closed, Err returns nil. 108 // If Done is closed, Err returns a non-nil error explaining why: 109 // Canceled if the context was canceled 110 // or DeadlineExceeded if the context's deadline passed. 111 // After Err returns a non-nil error, successive calls to Err return the same error. 112 Err() error 113 114 // Value returns the value associated with this context for key, or nil 115 // if no value is associated with key. Successive calls to Value with 116 // the same key returns the same result. 117 // 118 // Use context values only for request-scoped data that transits 119 // processes and API boundaries, not for passing optional parameters to 120 // functions. 121 // 122 // A key identifies a specific value in a Context. Functions that wish 123 // to store values in Context typically allocate a key in a global 124 // variable then use that key as the argument to context.WithValue and 125 // Context.Value. A key can be any type that supports equality; 126 // packages should define keys as an unexported type to avoid 127 // collisions. 128 // 129 // Packages that define a Context key should provide type-safe accessors 130 // for the values stored using that key: 131 // 132 // // Package user defines a User type that's stored in Contexts. 133 // package user 134 // 135 // import "context" 136 // 137 // // User is the type of value stored in the Contexts. 138 // type User struct {...} 139 // 140 // // key is an unexported type for keys defined in this package. 141 // // This prevents collisions with keys defined in other packages. 142 // type key int 143 // 144 // // userKey is the key for user.User values in Contexts. It is 145 // // unexported; clients use user.NewContext and user.FromContext 146 // // instead of using this key directly. 147 // var userKey key 148 // 149 // // NewContext returns a new Context that carries value u. 150 // func NewContext(ctx context.Context, u *User) context.Context { 151 // return context.WithValue(ctx, userKey, u) 152 // } 153 // 154 // // FromContext returns the User value stored in ctx, if any. 155 // func FromContext(ctx context.Context) (*User, bool) { 156 // u, ok := ctx.Value(userKey).(*User) 157 // return u, ok 158 // } 159 Value(key any) any 160 } 161 162 // Canceled is the error returned by Context.Err when the context is canceled. 163 var Canceled = errors.New("context canceled") 164 165 // DeadlineExceeded is the error returned by Context.Err when the context's 166 // deadline passes. 167 var DeadlineExceeded error = deadlineExceededError{} 168 169 type deadlineExceededError struct{} 170 171 func (deadlineExceededError) Error() string { return "context deadline exceeded" } 172 func (deadlineExceededError) Timeout() bool { return true } 173 func (deadlineExceededError) Temporary() bool { return true } 174 175 // An emptyCtx is never canceled, has no values, and has no deadline. It is not 176 // struct{}, since vars of this type must have distinct addresses. 177 type emptyCtx int 178 179 func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { 180 return 181 } 182 183 func (*emptyCtx) Done() <-chan struct{} { 184 return nil 185 } 186 187 func (*emptyCtx) Err() error { 188 return nil 189 } 190 191 func (*emptyCtx) Value(key any) any { 192 return nil 193 } 194 195 func (e *emptyCtx) String() string { 196 switch e { 197 case background: 198 return "context.Background" 199 case todo: 200 return "context.TODO" 201 } 202 return "unknown empty Context" 203 } 204 205 var ( 206 background = new(emptyCtx) 207 todo = new(emptyCtx) 208 ) 209 210 // Background returns a non-nil, empty Context. It is never canceled, has no 211 // values, and has no deadline. It is typically used by the main function, 212 // initialization, and tests, and as the top-level Context for incoming 213 // requests. 214 func Background() Context { 215 return background 216 } 217 218 // TODO returns a non-nil, empty Context. Code should use context.TODO when 219 // it's unclear which Context to use or it is not yet available (because the 220 // surrounding function has not yet been extended to accept a Context 221 // parameter). 222 func TODO() Context { 223 return todo 224 } 225 226 // A CancelFunc tells an operation to abandon its work. 227 // A CancelFunc does not wait for the work to stop. 228 // A CancelFunc may be called by multiple goroutines simultaneously. 229 // After the first call, subsequent calls to a CancelFunc do nothing. 230 type CancelFunc func() 231 232 // WithCancel returns a copy of parent with a new Done channel. The returned 233 // context's Done channel is closed when the returned cancel function is called 234 // or when the parent context's Done channel is closed, whichever happens first. 235 // 236 // Canceling this context releases resources associated with it, so code should 237 // call cancel as soon as the operations running in this Context complete. 238 func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { 239 c := withCancel(parent) 240 return c, func() { c.cancel(true, Canceled, nil) } 241 } 242 243 // A CancelCauseFunc behaves like a CancelFunc but additionally sets the cancellation cause. 244 // This cause can be retrieved by calling Cause on the canceled Context or on 245 // any of its derived Contexts. 246 // 247 // If the context has already been canceled, CancelCauseFunc does not set the cause. 248 // For example, if childContext is derived from parentContext: 249 // - if parentContext is canceled with cause1 before childContext is canceled with cause2, 250 // then Cause(parentContext) == Cause(childContext) == cause1 251 // - if childContext is canceled with cause2 before parentContext is canceled with cause1, 252 // then Cause(parentContext) == cause1 and Cause(childContext) == cause2 253 type CancelCauseFunc func(cause error) 254 255 // WithCancelCause behaves like WithCancel but returns a CancelCauseFunc instead of a CancelFunc. 256 // Calling cancel with a non-nil error (the "cause") records that error in ctx; 257 // it can then be retrieved using Cause(ctx). 258 // Calling cancel with nil sets the cause to Canceled. 259 // 260 // Example use: 261 // 262 // ctx, cancel := context.WithCancelCause(parent) 263 // cancel(myError) 264 // ctx.Err() // returns context.Canceled 265 // context.Cause(ctx) // returns myError 266 func WithCancelCause(parent Context) (ctx Context, cancel CancelCauseFunc) { 267 c := withCancel(parent) 268 return c, func(cause error) { c.cancel(true, Canceled, cause) } 269 } 270 271 func withCancel(parent Context) *cancelCtx { 272 if parent == nil { 273 panic("cannot create context from nil parent") 274 } 275 c := newCancelCtx(parent) 276 propagateCancel(parent, c) 277 return c 278 } 279 280 // Cause returns a non-nil error explaining why c was canceled. 281 // The first cancellation of c or one of its parents sets the cause. 282 // If that cancellation happened via a call to CancelCauseFunc(err), 283 // then Cause returns err. 284 // Otherwise Cause(c) returns the same value as c.Err(). 285 // Cause returns nil if c has not been canceled yet. 286 func Cause(c Context) error { 287 if cc, ok := c.Value(&cancelCtxKey).(*cancelCtx); ok { 288 cc.mu.Lock() 289 defer cc.mu.Unlock() 290 return cc.cause 291 } 292 return nil 293 } 294 295 // newCancelCtx returns an initialized cancelCtx. 296 func newCancelCtx(parent Context) *cancelCtx { 297 return &cancelCtx{Context: parent} 298 } 299 300 // goroutines counts the number of goroutines ever created; for testing. 301 var goroutines atomic.Int32 302 303 // propagateCancel arranges for child to be canceled when parent is. 304 func propagateCancel(parent Context, child canceler) { 305 done := parent.Done() 306 if done == nil { 307 return // parent is never canceled 308 } 309 310 select { 311 case <-done: 312 // parent is already canceled 313 child.cancel(false, parent.Err(), Cause(parent)) 314 return 315 default: 316 } 317 318 if p, ok := parentCancelCtx(parent); ok { 319 p.mu.Lock() 320 if p.err != nil { 321 // parent has already been canceled 322 child.cancel(false, p.err, p.cause) 323 } else { 324 if p.children == nil { 325 p.children = make(map[canceler]struct{}) 326 } 327 p.children[child] = struct{}{} 328 } 329 p.mu.Unlock() 330 } else { 331 goroutines.Add(1) 332 go func() { 333 select { 334 case <-parent.Done(): 335 child.cancel(false, parent.Err(), Cause(parent)) 336 case <-child.Done(): 337 } 338 }() 339 } 340 } 341 342 // &cancelCtxKey is the key that a cancelCtx returns itself for. 343 var cancelCtxKey int 344 345 // parentCancelCtx returns the underlying *cancelCtx for parent. 346 // It does this by looking up parent.Value(&cancelCtxKey) to find 347 // the innermost enclosing *cancelCtx and then checking whether 348 // parent.Done() matches that *cancelCtx. (If not, the *cancelCtx 349 // has been wrapped in a custom implementation providing a 350 // different done channel, in which case we should not bypass it.) 351 func parentCancelCtx(parent Context) (*cancelCtx, bool) { 352 done := parent.Done() 353 if done == closedchan || done == nil { 354 return nil, false 355 } 356 p, ok := parent.Value(&cancelCtxKey).(*cancelCtx) 357 if !ok { 358 return nil, false 359 } 360 pdone, _ := p.done.Load().(chan struct{}) 361 if pdone != done { 362 return nil, false 363 } 364 return p, true 365 } 366 367 // removeChild removes a context from its parent. 368 func removeChild(parent Context, child canceler) { 369 p, ok := parentCancelCtx(parent) 370 if !ok { 371 return 372 } 373 p.mu.Lock() 374 if p.children != nil { 375 delete(p.children, child) 376 } 377 p.mu.Unlock() 378 } 379 380 // A canceler is a context type that can be canceled directly. The 381 // implementations are *cancelCtx and *timerCtx. 382 type canceler interface { 383 cancel(removeFromParent bool, err, cause error) 384 Done() <-chan struct{} 385 } 386 387 // closedchan is a reusable closed channel. 388 var closedchan = make(chan struct{}) 389 390 func init() { 391 close(closedchan) 392 } 393 394 // A cancelCtx can be canceled. When canceled, it also cancels any children 395 // that implement canceler. 396 type cancelCtx struct { 397 Context 398 399 mu sync.Mutex // protects following fields 400 done atomic.Value // of chan struct{}, created lazily, closed by first cancel call 401 children map[canceler]struct{} // set to nil by the first cancel call 402 err error // set to non-nil by the first cancel call 403 cause error // set to non-nil by the first cancel call 404 } 405 406 func (c *cancelCtx) Value(key any) any { 407 if key == &cancelCtxKey { 408 return c 409 } 410 return value(c.Context, key) 411 } 412 413 func (c *cancelCtx) Done() <-chan struct{} { 414 d := c.done.Load() 415 if d != nil { 416 return d.(chan struct{}) 417 } 418 c.mu.Lock() 419 defer c.mu.Unlock() 420 d = c.done.Load() 421 if d == nil { 422 d = make(chan struct{}) 423 c.done.Store(d) 424 } 425 return d.(chan struct{}) 426 } 427 428 func (c *cancelCtx) Err() error { 429 c.mu.Lock() 430 err := c.err 431 c.mu.Unlock() 432 return err 433 } 434 435 type stringer interface { 436 String() string 437 } 438 439 func contextName(c Context) string { 440 if s, ok := c.(stringer); ok { 441 return s.String() 442 } 443 return reflectlite.TypeOf(c).String() 444 } 445 446 func (c *cancelCtx) String() string { 447 return contextName(c.Context) + ".WithCancel" 448 } 449 450 // cancel closes c.done, cancels each of c's children, and, if 451 // removeFromParent is true, removes c from its parent's children. 452 // cancel sets c.cause to cause if this is the first time c is canceled. 453 func (c *cancelCtx) cancel(removeFromParent bool, err, cause error) { 454 if err == nil { 455 panic("context: internal error: missing cancel error") 456 } 457 if cause == nil { 458 cause = err 459 } 460 c.mu.Lock() 461 if c.err != nil { 462 c.mu.Unlock() 463 return // already canceled 464 } 465 c.err = err 466 c.cause = cause 467 d, _ := c.done.Load().(chan struct{}) 468 if d == nil { 469 c.done.Store(closedchan) 470 } else { 471 close(d) 472 } 473 for child := range c.children { 474 // NOTE: acquiring the child's lock while holding parent's lock. 475 child.cancel(false, err, cause) 476 } 477 c.children = nil 478 c.mu.Unlock() 479 480 if removeFromParent { 481 removeChild(c.Context, c) 482 } 483 } 484 485 // WithDeadline returns a copy of the parent context with the deadline adjusted 486 // to be no later than d. If the parent's deadline is already earlier than d, 487 // WithDeadline(parent, d) is semantically equivalent to parent. The returned 488 // context's Done channel is closed when the deadline expires, when the returned 489 // cancel function is called, or when the parent context's Done channel is 490 // closed, whichever happens first. 491 // 492 // Canceling this context releases resources associated with it, so code should 493 // call cancel as soon as the operations running in this Context complete. 494 func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) { 495 if parent == nil { 496 panic("cannot create context from nil parent") 497 } 498 if cur, ok := parent.Deadline(); ok && cur.Before(d) { 499 // The current deadline is already sooner than the new one. 500 return WithCancel(parent) 501 } 502 c := &timerCtx{ 503 cancelCtx: newCancelCtx(parent), 504 deadline: d, 505 } 506 propagateCancel(parent, c) 507 dur := time.Until(d) 508 if dur <= 0 { 509 c.cancel(true, DeadlineExceeded, nil) // deadline has already passed 510 return c, func() { c.cancel(false, Canceled, nil) } 511 } 512 c.mu.Lock() 513 defer c.mu.Unlock() 514 if c.err == nil { 515 c.timer = time.AfterFunc(dur, func() { 516 c.cancel(true, DeadlineExceeded, nil) 517 }) 518 } 519 return c, func() { c.cancel(true, Canceled, nil) } 520 } 521 522 // A timerCtx carries a timer and a deadline. It embeds a cancelCtx to 523 // implement Done and Err. It implements cancel by stopping its timer then 524 // delegating to cancelCtx.cancel. 525 type timerCtx struct { 526 *cancelCtx 527 timer *time.Timer // Under cancelCtx.mu. 528 529 deadline time.Time 530 } 531 532 func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { 533 return c.deadline, true 534 } 535 536 func (c *timerCtx) String() string { 537 return contextName(c.cancelCtx.Context) + ".WithDeadline(" + 538 c.deadline.String() + " [" + 539 time.Until(c.deadline).String() + "])" 540 } 541 542 func (c *timerCtx) cancel(removeFromParent bool, err, cause error) { 543 c.cancelCtx.cancel(false, err, cause) 544 if removeFromParent { 545 // Remove this timerCtx from its parent cancelCtx's children. 546 removeChild(c.cancelCtx.Context, c) 547 } 548 c.mu.Lock() 549 if c.timer != nil { 550 c.timer.Stop() 551 c.timer = nil 552 } 553 c.mu.Unlock() 554 } 555 556 // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). 557 // 558 // Canceling this context releases resources associated with it, so code should 559 // call cancel as soon as the operations running in this Context complete: 560 // 561 // func slowOperationWithTimeout(ctx context.Context) (Result, error) { 562 // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) 563 // defer cancel() // releases resources if slowOperation completes before timeout elapses 564 // return slowOperation(ctx) 565 // } 566 func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { 567 return WithDeadline(parent, time.Now().Add(timeout)) 568 } 569 570 // WithValue returns a copy of parent in which the value associated with key is 571 // val. 572 // 573 // Use context Values only for request-scoped data that transits processes and 574 // APIs, not for passing optional parameters to functions. 575 // 576 // The provided key must be comparable and should not be of type 577 // string or any other built-in type to avoid collisions between 578 // packages using context. Users of WithValue should define their own 579 // types for keys. To avoid allocating when assigning to an 580 // interface{}, context keys often have concrete type 581 // struct{}. Alternatively, exported context key variables' static 582 // type should be a pointer or interface. 583 func WithValue(parent Context, key, val any) Context { 584 if parent == nil { 585 panic("cannot create context from nil parent") 586 } 587 if key == nil { 588 panic("nil key") 589 } 590 if !reflectlite.TypeOf(key).Comparable() { 591 panic("key is not comparable") 592 } 593 return &valueCtx{parent, key, val} 594 } 595 596 // A valueCtx carries a key-value pair. It implements Value for that key and 597 // delegates all other calls to the embedded Context. 598 type valueCtx struct { 599 Context 600 key, val any 601 } 602 603 // stringify tries a bit to stringify v, without using fmt, since we don't 604 // want context depending on the unicode tables. This is only used by 605 // *valueCtx.String(). 606 func stringify(v any) string { 607 switch s := v.(type) { 608 case stringer: 609 return s.String() 610 case string: 611 return s 612 } 613 return "<not Stringer>" 614 } 615 616 func (c *valueCtx) String() string { 617 return contextName(c.Context) + ".WithValue(type " + 618 reflectlite.TypeOf(c.key).String() + 619 ", val " + stringify(c.val) + ")" 620 } 621 622 func (c *valueCtx) Value(key any) any { 623 if c.key == key { 624 return c.val 625 } 626 return value(c.Context, key) 627 } 628 629 func value(c Context, key any) any { 630 for { 631 switch ctx := c.(type) { 632 case *valueCtx: 633 if key == ctx.key { 634 return ctx.val 635 } 636 c = ctx.Context 637 case *cancelCtx: 638 if key == &cancelCtxKey { 639 return c 640 } 641 c = ctx.Context 642 case *timerCtx: 643 if key == &cancelCtxKey { 644 return ctx.cancelCtx 645 } 646 c = ctx.Context 647 case *emptyCtx: 648 return nil 649 default: 650 return c.Value(key) 651 } 652 } 653 } 654