3

I have some goroutine logics like this:

go func() {
    do_things_0()
    do_things_1()
    do_things_2()
    do_things_3()
    ...
    ...
} ()

When the service receives a request, it will create such goroutine. And the goroutine maybe memory consuming and needs to run more than 30 minutes.

Sometimes, the service may notice the lack of memory, and needs to terminate some goroutines.

My questions are:

  1. How can I terminate the goroutine in the above example?
  2. Is there any way to know the used memory of each goroutine?

Update

  1. I read other SO answers that goroutine can't be killed outside
  2. I suppose that send a signal to the channel handled by the goroutine to make the goroutine quit is only suitable for the for loop based logics.
  3. I am looking for some best practice to close the goroutine for the flow based logics.
pengdu
  • 1,331
  • 2
  • 14
  • 21
  • 1
    1) You cannot (see below). 2) There is no way to do this. To "stop" a goroutine you have to invent a mechanism to kill it from the outside (e.g. by closing a channel handled to the goroutine). – Volker Sep 22 '16 at 08:11
  • 2
    You can't stop / kill a goroutine. See related question: [cancel a blocking operation in Go](http://stackoverflow.com/questions/28240133/cancel-a-blocking-operation-in-go) – icza Sep 22 '16 at 08:16
  • @Volker I know that I can close a channel to make the goroutine close, but I suppose it's only useful for the goroutine which runs a for loop like logic. I don't find a convenient way to close a goroutine for such flow based goroutine. – pengdu Sep 22 '16 at 08:21
  • @icza Do you have any idea about how to send a signal to close a flow based goroutine? – pengdu Sep 22 '16 at 08:22
  • 1
    @pengdu Usually a signalling channel is closed. See some examples: [one](http://stackoverflow.com/questions/32383063/shutdown-worker-go-routine-after-buffer-is-empty), [two](http://stackoverflow.com/questions/28958192/whats-wrong-with-this-golang-code), [three](http://stackoverflow.com/questions/38170852/is-this-an-idiomatic-worker-thread-pool-in-go/38172204#38172204), [four](http://stackoverflow.com/questions/34464146/the-idiomatic-way-to-implement-generators-yield-in-golang-for-recursive-functi/34466755#34466755) – icza Sep 22 '16 at 08:24

1 Answers1

1

You should be able to adapt this easily to a for loop if you range over a list of the functions that are your steps:

package main

import (
    "fmt"
    "time"
)

func a() { fmt.Printf("a") }
func b() { fmt.Printf("b") }
func c() { fmt.Printf("c") }
func d() { fmt.Printf("d") }
func e() { fmt.Printf("e") }

func f(quit <-chan struct{}) {
    for i := 0; i < 10000; i++ {
        for _, fn := range []func(){a, b, c, d, e} {
            select {
            case _, _ = <-quit:
                fmt.Println("quit f")
                return
            default:
                fn()
                time.Sleep(1 * time.Millisecond)
            }
        }
    }
}

func main() {
    quit := make(chan struct{})
    fmt.Println("go f")
    go f(quit)
    fmt.Println("sleep")
    time.Sleep(100 * time.Millisecond)
    fmt.Println("\nquit")
    close(quit)
    time.Sleep(10 * time.Millisecond)
    fmt.Println("exit")
}

Try it on the playground.

The outer loop is just there to repeat the steps for long enough that we can witness the quit command happening.

Snargleplax
  • 185
  • 1
  • 5