The reason why the other goroutines can't run is garbage collection. Because there is one goroutine that's not responding to the runtime's stop request, the runtime can't finish the garbage collection. That outstanding goroutine might have pointers to otherwise unreachable objects. The runtime can't look at the pointers a goroutine has until it can get the goroutine to stop. The runtime can't let the other goroutines keep running at this point. It needs to finish the garbage collection so that it can reclaim memory. Otherwise your program's pathological behavior would switch from hanging to OOMing.
On Wednesday, June 21, 2017 at 12:36:43 PM UTC-7, David Chase wrote: > > Try compiling your code with -gcflags -d=ssa/insert_resched_checks/on . > You should see the scheduler thrashing stop, at the expense of some loop > overhead. > (The simpler the loop, the worse the overhead, that is why this phase is > not normally enabled. > We're working on the overhead issues, they've not been easy so far.) > > On Tuesday, June 20, 2017 at 11:40:12 PM UTC-4, Ronald wrote: >> >> Hi, I found when running this code below (play >> <https://play.golang.org/p/XyxV_1f6Ri>): >> >> >> package main >> import "fmt" >> import "runtime" >> import "time" >> type callRet struct { >> ret int >> } >> type callIn struct { >> ret_chan chan *callRet >> arg1 int >> } >> func caller(call_in_c chan *callIn, arg1 int) int { >> ret_c := make(chan *callRet, 1) >> ci := callIn{ret_c, arg1} >> t1 := time.Now().UnixNano() >> call_in_c <- &ci >> ret := <-ret_c >> t2 := time.Now().UnixNano() >> _, _ = t1, t2 >> //fmt.Println(t2, t1, float64(t2-t1)/1e6) >> return ret.ret >> } >> func call_srv(call_in_c chan *callIn) { >> //runtime.LockOSThread() >> ct := 0 >> for { >> select { >> case in := <-call_in_c: >> ret_c := in.ret_chan >> ret := callRet{3 + in.arg1} >> ret_c <- &ret >> ct++ >> if ct%1000 == 0 { >> fmt.Println(ct) >> } >> //default: >> // time.Sleep(1 * time.Millisecond) >> } >> } >> //runtime.UnlockOSThread() >> } >> func init() { >> //runtime.LockOSThread() >> } >> func main() { >> p := fmt.Println >> runtime.GOMAXPROCS(5) >> call_in_c := make(chan *callIn, 2000) >> fp := func(call_in_c chan *callIn) { >> ct := 0 >> for ; ct < 2000000; ct = ct + 1 { >> caller(call_in_c, 1) >> time.Sleep(100 * time.Nanosecond) >> } >> p("done:)") >> } >> go fp(call_in_c) >> go fp(call_in_c) >> go func() { >> for { >> fmt.Println("heartbeat...") >> time.Sleep(10 * 1000 * time.Microsecond) >> } >> }() >> >> // after delete this little piece code, it will be ok >> >> go func() { >> for { >> } >> }() >> >> // -^ >> >> call_srv(call_in_c) >> return >> } >> >> It will always “stuck” in certain time after start executing (tested in >> both go 1.7 , 1.8.1 and 1.8.3, >> and you should run it on your own computer, not on the play because it >> would cost several seconds). >> I have checked the code above dozens of times at least and sure it is all >> right. >> >> I tried to attach the go process with gdb when it is stuck and the `bt` >> yielded this: >> >> >>> (gdb) info goroutines >>> 1 waiting runtime.gopark >>> 2 waiting runtime.gopark >>> 3 waiting runtime.gopark >>> 4 waiting runtime.gopark >>> 5 waiting runtime.gopark >>> * 6 running runtime.systemstack_switch >>> 7 waiting runtime.gopark >>> * 8 running main.main.func3 >>> 17 runnable runtime.exitsyscall >>> 33 waiting runtime.gopark >>> 18 waiting runtime.gopark >>> 49 waiting runtime.gopark >>> 50 waiting runtime.gopark >>> 51 waiting runtime.gopark >>> (gdb) goroutine 6 bt >>> #0 runtime.systemstack_switch () at >>> /usr/local/go/src/runtime/asm_amd64.s:281 >>> #1 0x0000000000415088 in runtime.gcStart (mode=0, forceTrigger=false) >>> at /usr/local/go/src/runtime/mgc.go:1010 >>> #2 0x000000000040d841 in runtime.mallocgc (size=96, typ=0x4a7fa0, >>> needzero=true, >>> ~r3=0x507998 <runtime.timers+24>) at >>> /usr/local/go/src/runtime/malloc.go:785 >>> #3 0x000000000040df68 in runtime.newobject (typ=0x4a7fa0, ~r1=0x0) >>> at /usr/local/go/src/runtime/malloc.go:820 >>> #4 0x00000000004035d2 in runtime.makechan (t=0x492960, size=1, >>> ~r2=0xc4200016c0) >>> at /usr/local/go/src/runtime/chan.go:92 >>> #5 0x00000000004840e4 in main.caller (call_in_c=0xc420056060, arg1=1, >>> ~r2=0) >>> at /root/go/src/chan/x.go:18 >>> #6 0x00000000004846ac in main.main.func1 (call_in_c=0xc420056060) at >>> /root/go/src/chan/x.go:62 >>> #7 0x000000000044da21 in runtime.goexit () at >>> /usr/local/go/src/runtime/asm_amd64.s:2197 >>> #8 0x000000c420056060 in ?? () >>> #9 0x0000000000000000 in ?? () >> >> >> >> -- 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+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.