Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens if I don't cancel a Context?

Tags:

go

I have the following code:

func Call(ctx context.Context, payload Payload) (Response, error) {
    req, err := http.NewRequest(...) // Some code that creates request from payload
    ctx, cancel = context.withTimeout(ctx, time.Duration(3) * time.Second)
    defer cancel()
    return http.DefaultClient.Do(req)
}

What would happen if I didn't put defer cancel() in there? go vet warned this

the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak

How will the context be leaked and what impact will this have? Thanks

like image 452
stackoverflower Avatar asked Jun 06 '17 15:06

stackoverflower


People also ask

When should you cancel context?

That context is canceled if the HTTP client disconnects or cancels the HTTP request (possible in HTTP/2). Passing an HTTP request's context to QueryWithTimeout above would cause the database query to stop early either if the overall HTTP request was canceled or if the query took more than five seconds.

What happens when context is Cancelled?

In some cases you can see “proxy error: context canceled” error message in the Gateway logs. The error itself means that the connection was closed unexpectedly. It can happen for various reasons, and in some cases it is totally fine: for example client can have unstable mobile internet.

Does Cancelling a child context cancel parent?

The converse is false however: a canceled child context does not cancel its parent. Additionally, attaching values results in a new child context for each new key-value pair without mutating the parent.

What does context background Return?

Background returns a non-nil, empty Context. It is never canceled, has no values, and has no deadline. It is typically used by the main function, initialization, and tests, and as the top-level Context for incoming requests.


2 Answers

If you fail to cancel the context, the goroutine that WithCancel or WithTimeout created will be retained in memory indefinitely (until the program shuts down), causing a memory leak. If you do this a lot, your memory will balloon significantly. It's best practice to use a defer cancel() immediately after calling WithCancel() or WithTimeout()

like image 175
Kaedys Avatar answered Oct 11 '22 07:10

Kaedys


If you use WithCancel, the goroutine will be held indefinitely in memory. However, if you use WithDeadline or WithTimeout without calling cancel, the goroutine will only be held until the timer expires.

This is still not best practice though, it's always best to call cancel as soon as you're done with the resource.

like image 22
user4436000 Avatar answered Oct 11 '22 09:10

user4436000