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.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
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.I'm not sure how it's *meant* to be used, but a way to do it, while adhering to everything you say, is to usedefer cancel()In that case, a) cancel will always be called at least once, b) if you want to cancel it before, you can. Just call cancel and c) if you call ctx.Err() (e.g. in a return statement) it will return Cancelled iff you called cancel before in the same function.So, yes. If you get a cancel function, always make sure to call it (you might use go vet for that) at least once and a simple way to ensure that would be defer.
AIUI: A child or grandchild function is not supposed to signal that. They can return an error and let the parent cancel, or they can create their own child context WithCancel and cancel that. Context doesn't replace exceptions.
You should consider context a way to implement dynamic scoping. A context is a thing valid for the current stack frame and downwards and should never affect the stack upwards. Which is also why there's the "put values in there, not pointers" rule; if you have a pointer, it might modify an upstack context.The advantage of that (and context in general) is, that you don't need to worry too much about synchronization and everything; as a context is fundamentally immutable (-ish), it's fine to pass it to separate goroutines, because they can only do stuff with it downstack.
On Wed, Nov 2, 2016, at 12:56 PM, 'Axel Wagner' via golang-nuts wrote:AIUI: A child or grandchild function is not supposed to signal that. They can return an error and let the parent cancel, or they can create their own child context WithCancel and cancel that. Context doesn't replace exceptions.OK I see that. I think I don't understand the purpose of the Err method if the function that creates the context is the one that cancels it or closes the Done channel. It seems that the only purpose would be to detect a Timeout.
You should consider context a way to implement dynamic scoping. A context is a thing valid for the current stack frame and downwards and should never affect the stack upwards. Which is also why there's the "put values in there, not pointers" rule; if you have a pointer, it might modify an upstack context.The advantage of that (and context in general) is, that you don't need to worry too much about synchronization and everything; as a context is fundamentally immutable (-ish), it's fine to pass it to separate goroutines, because they can only do stuff with it downstack.Yes, this is what I am trying to do. I was wondering whether the returned cancelFunc is something that could be passed downstream to signal parents that work should be aborted.
Hello there,On Wed, Nov 2, 2016 at 11:09 AM, Ian Davis <m...@iandavis.com> wrote:On Wed, Nov 2, 2016, at 12:56 PM, 'Axel Wagner' via golang-nuts wrote:AIUI: A child or grandchild function is not supposed to signal that. They can return an error and let the parent cancel, or they can create their own child context WithCancel and cancel that. Context doesn't replace exceptions.OK I see that. I think I don't understand the purpose of the Err method if the function that creates the context is the one that cancels it or closes the Done channel. It seems that the only purpose would be to detect a Timeout.Err allows you to do this:select {case <-ctx.Done():return ctx.Err()...}
You should consider context a way to implement dynamic scoping. A context is a thing valid for the current stack frame and downwards and should never affect the stack upwards. Which is also why there's the "put values in there, not pointers" rule; if you have a pointer, it might modify an upstack context.The advantage of that (and context in general) is, that you don't need to worry too much about synchronization and everything; as a context is fundamentally immutable (-ish), it's fine to pass it to separate goroutines, because they can only do stuff with it downstack.Yes, this is what I am trying to do. I was wondering whether the returned cancelFunc is something that could be passed downstream to signal parents that work should be aborted.No, the purpose of Context is the opposite: fired tasks are free to do whatever they please until it's time to stop, because the boss says so. Once that happens, error propagation happens as usual to tell what went wrong.The http://gopkg.in/tomb.v2 package works closer to the model you describe.
On Wed, Nov 2, 2016, at 10:35 PM, Gustavo Niemeyer wrote:Hello there,On Wed, Nov 2, 2016 at 11:09 AM, Ian Davis <m...@iandavis.com> wrote:On Wed, Nov 2, 2016, at 12:56 PM, 'Axel Wagner' via golang-nuts wrote:AIUI: A child or grandchild function is not supposed to signal that. They can return an error and let the parent cancel, or they can create their own child context WithCancel and cancel that. Context doesn't replace exceptions.OK I see that. I think I don't understand the purpose of the Err method if the function that creates the context is the one that cancels it or closes the Done channel. It seems that the only purpose would be to detect a Timeout.Err allows you to do this:select {case <-ctx.Done():return ctx.Err()...}In this situation, other than a timeout, what would be closing the Done channel? The goroutine that created the context already knows the error since it's the only one that is supposed to call cancel.
You should consider context a way to implement dynamic scoping. A context is a thing valid for the current stack frame and downwards and should never affect the stack upwards. Which is also why there's the "put values in there, not pointers" rule; if you have a pointer, it might modify an upstack context.The advantage of that (and context in general) is, that you don't need to worry too much about synchronization and everything; as a context is fundamentally immutable (-ish), it's fine to pass it to separate goroutines, because they can only do stuff with it downstack.Yes, this is what I am trying to do. I was wondering whether the returned cancelFunc is something that could be passed downstream to signal parents that work should be aborted.No, the purpose of Context is the opposite: fired tasks are free to do whatever they please until it's time to stop, because the boss says so. Once that happens, error propagation happens as usual to tell what went wrong.The http://gopkg.in/tomb.v2 package works closer to the model you describe.Thanks. I've used tomb before and I've played with the context/tomb integration. I guess I need both.
--
That is actually a great point I haven't thought about and the crux of the matter (sorry for repeating it, but I think it's worth making very explicit):While cancelFunc can only be called from the goroutine that created the context, Err can be called downstack. Meaning, if I call cancelFunc, a call *might or might not* return Cancelled as an error. It might not actually implement cancellation or the call might have failed or succeeded concurrently with a different (non-)error.
The ctx.Err() return thus allows a "child-function" to signal back whether a cancellation was *successful*; the creator of the context only know that it has been *tried*.
You said the function would return whether it got cancelled or not, so I assumed something like err := foo.CallAPI(ctx), which would be awkward to return without actually canceling.
Yes, if the function is documented to return with background activity, it's of course fine. That said, It's extremely helpful to be able to reliably cancel such background activity and wait until it's done, for a number of reasons: side effect control, testing, polite shutdowns, etc.
That's mainly where gopkg.in/tomb.v2 comes from.
Glad it's being useful, and indeed, that API looks familiar. Nice.