Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

question: is it possible to a goroutine immediately stop another goroutine? #32610

Closed
KHs000 opened this issue Jun 13, 2019 · 6 comments
Closed

Comments

@KHs000
Copy link

KHs000 commented Jun 13, 2019

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?

@josharian
Copy link
Contributor

runtime.Goexit?

@KHs000
Copy link
Author

KHs000 commented Jun 14, 2019

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:

  • signalizing in a channel that the the other routine should stop (but this approach has the problem that it's not immediately terminating the other goroutine, thus it would finalize, possible generating unwanted behavior)
  • make the goroutine that is supposed to be stopped, check a variable after every step of it's execution to be sure it's safe to keep running. Leading to a very messy code with tons of ifs and returns

I'll edit the title of the issue to better reflect the true nature of the question.

@KHs000 KHs000 changed the title question: is it possible to immediately stop a goroutine? question: is it possible to a goroutine immediately stop another goroutine? Jun 14, 2019
@davecheney
Copy link
Contributor

davecheney commented Jun 14, 2019

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?

@ianlancetaylor
Copy link
Contributor

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 .

@KHs000
Copy link
Author

KHs000 commented Jun 14, 2019

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.

@sonu0702
Copy link

Could you share your solution.

@golang golang locked and limited conversation to collaborators May 19, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants