Created
September 22, 2019 17:11
-
-
Save ezdiy/7be7d161f75980980fd5bdfc5dffa42b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Bug - this program should terminate. It doesn't. Why? | |
package main | |
import ( | |
"log" | |
"runtime" | |
"sync" | |
"sync/atomic" | |
) | |
const forceSchedule = false | |
func main() { | |
var stop uint32 | |
var wg sync.WaitGroup | |
wg.Add(1) | |
// Pure compute goroutine which doesn't spam gc, doesn't talk to mutexes, nor does any I/O. It merely | |
// checks atomic flag to be told to stop computing. | |
go func() { | |
for atomic.LoadUint32(&stop) == 0 { | |
// If forceSchedule is true, everything works fine. | |
// It seems that scheduler at the other end simply presumes that it will get an in to | |
// here *eventually*. But that creates a deadlock condition - scheduler own's waiting for | |
// this chance stops this goroutine from that chance (by setting stop=1) to happen. | |
if forceSchedule { | |
runtime.Gosched() | |
} | |
} | |
log.Println("compute terminating") | |
wg.Done() | |
}() | |
// This is a manager goroutine which does normal go stuff, networking io, generating garbage etc. | |
// eventually it tells the compute goroutine to halt. | |
var y *int | |
for x := 0; x < 1000000; x++ { | |
// trigger gc which seems to trip mcall() to scheduler and that gets stuck | |
// on the compute goroutine. This thread now hangs here on a mutex waiting for compute goroutine to schedule, | |
// thus barring us from delivering stop condition allowing the schedule in the first place. | |
y = new(int) | |
} | |
_ = y | |
atomic.StoreUint32(&stop, 1) | |
wg.Wait() | |
log.Println("done") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment