go: runtime: tight loop hangs process completely after some time

Please answer these questions before submitting your issue. Thanks!

  1. What version of Go are you using (go version)? go version go1.6.2 windows/amd64
  2. What operating system and processor architecture are you using (go env)? Windows 10.0.10586 am64
  3. What did you do? Ran this code
package main

import (
    "log"
    "runtime"
)

func main() {
    runtime.GOMAXPROCS(2)
    ch := make(chan bool)

    go func() {
        for {
            ch <- true
            log.Println("sent")
        }
    }()

    go func() {
        for {
            <-ch
            log.Println("received")
        }
    }()

    for {   
    }
}
  1. What did you expect to see? Process printing “sent” and “received” until terminated
  2. What did you see instead? Process runs and prints as expected for about 2 seconds and then hangs. Nothing is printed after that, process just eats up CPU. No panics or anything.

I put runtime.GOMAXPROCS(2) to make sure that there’re multiple threads that goroutines can ran on. Obviously with runtime.GOMAXPROCS(1) process would hang immediately as expected - for loop will not yield execution.

I tried to replace the for loop with this so that main goroutine can yield execution:

go func() {
    for {
    }
}()

select {}

But exactly the same thing happens. Now, if I put time.Sleep(10 * time.Millisecond) or longer after log.Println("sent") then process no longer hangs. I ran it for a minute and it’s just kept going. Don’t know, maybe it will still hang much later. If I change it to 2 ms then it hangs after 30 seconds. I tried to collect trace data but it looks like it gets corrupted because trace doesn’t finish. When I try to view the trace it says “failed to parse trace: no EvFrequency event”.

Everything behaves exactly the same on Mac OSX El capitan 10.11.4 (15E65) Go 1.6.2

I read the #10958 but here the weird thing is that it actually runs for awhile completely fine and only after that it hangs.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 26 (16 by maintainers)

Most upvoted comments

I’m sorry this seems unrelated to the original issue. The reason for using select {} over for {} is they both block the current goroutine from making any further progress, but the former does it by removing the goroutine from the scheduler (as none if its zero cases are selectable), the latter does so by spinning in a loop which cannot be interrupted.

If you believe there is a bug, can you please produce a runnable sample that does not use a for {} loop, preferably on play.golang.org, that demonstrates the issue.