I need that the Golang scheduler run all goroutines before continue, runtime.Gosched() does not solve.
The problem is that the go routine can run so fast that the "select" in start() run after the "select" inside de stopStream(), then the "case <-chanStopStream:" receiver is not ready to the sender "case retChan <- true:". The result is that when this happen the result is the same behavior from when stopStream() hangs
Run this code https://go.dev/play/p/DQ85XqjU2Q_z many times that you will see this both responses Expected response when NOT hang:
2009/11/10 23:00:00 Start
2009/11/10 23:00:00 receive chan
2009/11/10 23:00:03 end
Expected response when hang, but not when is so fast:
2009/11/10 23:00:00 Start
2009/11/10 23:00:00 default
2009/11/10 23:00:01 TIMER
2009/11/10 23:00:04 end
The code
package main
import (
"log"
"runtime"
"sync"
"time"
)
var wg sync.WaitGroup
func main() {
wg.Add(1)
//run multiples routines on a huge system
go start()
wg.Wait()
}
func start() {
log.Println("Start")
chanStopStream := make(chan bool)
go stopStream(chanStopStream)
select {
case <-chanStopStream:
log.Println("receive chan")
case <-time.After(time.Second): //if stopStream hangs do not wait more than 1 second
log.Println("TIMER")
//call some crash alert
}
time.Sleep(3 * time.Second)
log.Println("end")
wg.Done()
}
func stopStream(retChan chan bool) {
//do some work that can be faster then caller or not
runtime.Gosched()
//time.Sleep(time.Microsecond) //better solution then runtime.Gosched()
//time.Sleep(2 * time.Second) //simulate when this routine hangs more than 1 second
select {
case retChan <- true:
default: //select/default is used because if the caller times out this routine will hangs forever
log.Println("default")
}
}