Go

What is preemption in Go? Explain cooperative vs. asynchronous preemption (Go 1.14).

Question 152HardGo 1.22 to 1.25

Before Go 1.14, preemption was cooperative. sysmon marked a goroutine that had run for more than about 10 ms by setting its stack guard to stackPreempt. The goroutine noticed the mark only at a function prologue during its stack check. A tight loop with no function calls, such as for {} or pure arithmetic, never reached that check. It could hold a P forever and stall GC stop-the-world phases, which could freeze the whole program.

Go 1.14 added asynchronous preemption. sysmon or the GC sends the thread a signal (SIGURG on Unix, thread suspension on Windows). The signal handler checks that the goroutine is at an async safe point. If it is, the handler injects a call to asyncPreempt, which saves all registers and yields.

Gotchas:

  • Code running in cgo, in assembly marked unsafe for preemption, or in some runtime sections still cannot be preempted.
  • Syscalls can be interrupted by EINTR. Go's standard library retries them, but your own raw syscalls or cgo code may need to handle it.
  • You can disable async preemption with GODEBUG=asyncpreemptoff=1 to debug.

More on Goroutines & the Scheduler

All 35 Goroutines & the Scheduler questions