Taking for example the following code:
package main
import (
"fmt"
"time"
"sync"
)
func secondaryProcess(closeCh chan bool, wg *sync.WaitGroup) {
for {
select {
case _ = <- closeCh:
fmt.Println("got a close signal")
wg.Done()
return
default:
fmt.Println("still running")
time.Sleep(5*time.Second)
}
}
}
func main() {
ch := make(chan bool)
var wg sync.WaitGroup
wg.Add(2)
go func() {
fmt.Println("going to sleep")
time.Sleep(1*time.Second)
fmt.Println("woke up")
ch <- true
wg.Done()
}()
go secondaryProcess(ch, &wg)
wg.Wait()
}
(Link for it in the playground)
After sending something in the channel which signals the secondaryProcess to stop, the program will only exit after the Sleep initiated in the default is finished, since it was already started it makes sense that it would be entirely executed. But I could not find a way to immediately stop the execution of the function at a given moment. I tried searching about a way to do this, but after some time reading posts, blogs, etc, it seemed that there's no way to effectively kill a goroutine after it started. Once it begins, it'll run thoroughly until it finishes or encounter an error. So my question is:
Is it possible to completely stop the execution of a goroutine at a given moment, not allowing it to finish it's processing?
If not, was it another behavior that golang purposely choose not to implement?
runtime.Goexit?
I've notice that my question has a certain vagueness, "is it possible to immediately stop a goroutine?", Goexit indeed can terminate a goroutine, but only the one that called it. That's not quite the behavior I'm looking for. What I want is something like goroutine A immediately terminating the execution of goroutine B.
Like, suppose that in my example, the secondaryProcess was just a infinite loop that would do something, sleep for a while and repeat. At some point, the anonymous goroutine in the main would decide to stop that process. The ways I've found to achieve it would either be:
I'll edit the title of the issue to better reflect the true nature of the question.
Stopping another process, another thread, another goroutine is tricky. The act of saying "operating system stop giving cpu cycles to that thread" sounds simple to achieve, but the results are profound. If the process, thread, or goroutine stops dead in its tracks -- what happens to the resource's it owned? Is the stack unwound? Are defer blocks executed? If so, then the goroutine could continue to live indefinitely as defer blocks run. If defer blocks are not run then that presents the situation where any goroutine can corrupt any invariant of your system by taking a lock, then being shot dead on the spot. There are no suitable answers for these design challenges that do not spawn more questions like "how can I prevent my goroutine from being killed?", etc.
To step back a bit, assuming that there was a mechanism to get a handle on another goroutine, and through that handle stop the goroutine, either unwinding it's stack and executing any defer blocks, or just kicking it out of the scheduler on the spot, what would that allow you to do that you cannot currently do? What is the problem that you are trying to solve by allowing one goroutine to stop another?
The short answer to your question is no, there is no way to do that.
I recommend that you take this to a forum rather than the issue tracker. See https://golang.org/wiki/Questions .
Thank you all for the answers so far.
I'll do as recommended by @ianlancetaylor and take this to the Go Forum. There I'll go into more depth about the problem me and a co-worker though we could solve using this principle. Although we ended up using another solution which was better and far more simple, we remain curious if it would be possible to solve the problem by having a goroutine kill another.
Could you share your solution.
Most helpful comment
Could you share your solution.