From f966695ccea356e4e4e8cc0328276e2d00c9fc1e Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Fri, 3 Jan 2025 11:47:39 -0800 Subject: [PATCH] context: use "canceled" in docs to refer to timed-out contexts In documentation, we've usually but not always referred to a context with a closed Done channel as "done" rather than "canceled", to avoid ambiguity between a context canceled by calling a CancelFunc and one past its deadline. This actually adds ambiguity, however, since it's common to see references to a "canceled context" that are intended to cover contexts past their deadline. If you see "function F returns if its context is canceled", you can reasonably assume that F will return if its context passes its deadline, unless something says otherwise. Update the context package docs to explicitly state that a context is canceled when its deadline passes. Drop references to contexts becoming "done" and just use "canceled" throughout. Fixes #70945 Change-Id: I99fbd800c6049deaa37015a304f7f9d9a84100e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/640095 Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Auto-Submit: Damien Neil --- src/context/context.go | 42 +++++++++++++++++++------------------ src/context/example_test.go | 4 ++-- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/context/context.go b/src/context/context.go index db8bc69553ebe8..bef9e8aab054d6 100644 --- a/src/context/context.go +++ b/src/context/context.go @@ -10,23 +10,25 @@ // calls to servers should accept a Context. The chain of function // calls between them must propagate the Context, optionally replacing // it with a derived Context created using [WithCancel], [WithDeadline], -// [WithTimeout], or [WithValue]. When a Context is canceled, all -// Contexts derived from it are also canceled. +// [WithTimeout], or [WithValue]. +// +// A Context may be canceled to indicate that work done on its behalf should stop. +// A Context with a deadline is canceled after the deadline passes. +// When a Context is canceled, all Contexts derived from it are also canceled. // // The [WithCancel], [WithDeadline], and [WithTimeout] functions take a // Context (the parent) and return a derived Context (the child) and a -// [CancelFunc]. Calling the CancelFunc cancels the child and its +// [CancelFunc]. Calling the CancelFunc directly cancels the child and its // children, removes the parent's reference to the child, and stops // any associated timers. Failing to call the CancelFunc leaks the -// child and its children until the parent is canceled or the timer -// fires. The go vet tool checks that CancelFuncs are used on all -// control-flow paths. +// child and its children until the parent is canceled. The go vet tool +// checks that CancelFuncs are used on all control-flow paths. // -// The [WithCancelCause] function returns a [CancelCauseFunc], which -// takes an error and records it as the cancellation cause. Calling -// [Cause] on the canceled context or any of its children retrieves -// the cause. If no cause is specified, Cause(ctx) returns the same -// value as ctx.Err(). +// The [WithCancelCause], [WithDeadlineCause], and [WithTimeoutCause] functions +// return a [CancelCauseFunc], which takes an error and records it as +// the cancellation cause. Calling [Cause] on the canceled context +// or any of its children retrieves the cause. If no cause is specified, +// Cause(ctx) returns the same value as ctx.Err(). // // Programs that use Contexts should follow these rules to keep interfaces // consistent across packages and enable static analysis tools to check context @@ -107,8 +109,8 @@ type Context interface { // If Done is not yet closed, Err returns nil. // If Done is closed, Err returns a non-nil error explaining why: - // Canceled if the context was canceled - // or DeadlineExceeded if the context's deadline passed. + // DeadlineExceeded if the context's deadline passed, + // or Canceled if the context was canceled for some other reason. // After Err returns a non-nil error, successive calls to Err return the same error. Err() error @@ -160,11 +162,12 @@ type Context interface { Value(key any) any } -// Canceled is the error returned by [Context.Err] when the context is canceled. +// Canceled is the error returned by [Context.Err] when the context is canceled +// for some reason other than its deadline passing. var Canceled = errors.New("context canceled") -// DeadlineExceeded is the error returned by [Context.Err] when the context's -// deadline passes. +// DeadlineExceeded is the error returned by [Context.Err] when the context is canceled +// due to its deadline passing. var DeadlineExceeded error = deadlineExceededError{} type deadlineExceededError struct{} @@ -296,9 +299,8 @@ func Cause(c Context) error { return c.Err() } -// AfterFunc arranges to call f in its own goroutine after ctx is done -// (canceled or timed out). -// If ctx is already done, AfterFunc calls f immediately in its own goroutine. +// AfterFunc arranges to call f in its own goroutine after ctx is canceled. +// If ctx is already canceled, AfterFunc calls f immediately in its own goroutine. // // Multiple calls to AfterFunc on a context operate independently; // one does not replace another. @@ -306,7 +308,7 @@ func Cause(c Context) error { // Calling the returned stop function stops the association of ctx with f. // It returns true if the call stopped f from being run. // If stop returns false, -// either the context is done and f has been started in its own goroutine; +// either the context is canceled and f has been started in its own goroutine; // or f was already stopped. // The stop function does not wait for f to complete before returning. // If the caller needs to know whether f is completed, diff --git a/src/context/example_test.go b/src/context/example_test.go index b597b09f16e525..be8cd8376e1736 100644 --- a/src/context/example_test.go +++ b/src/context/example_test.go @@ -146,8 +146,8 @@ func ExampleAfterFunc_cond() { defer stopf() // Since the wakeups are using Broadcast instead of Signal, this call to - // Wait may unblock due to some other goroutine's context becoming done, - // so to be sure that ctx is actually done we need to check it in a loop. + // Wait may unblock due to some other goroutine's context being canceled, + // so to be sure that ctx is actually canceled we need to check it in a loop. for !conditionMet() { cond.Wait() if ctx.Err() != nil {