mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 02:57:46 +00:00
16fc1ea2bb
Match the Go runtime by terminating for deadlocks, stack overflows, runtime and GC invariants, invalid lock operations, and platform initialization failures instead of routing them through panic/recover. Keep language-level runtime errors and unsupported user operations recoverable. Add crash coverage that verifies fatal errors bypass deferred recover calls.
43 lines
909 B
Go
43 lines
909 B
Go
//go:build scheduler.tasks || scheduler.asyncify || scheduler.cores
|
|
|
|
package task
|
|
|
|
import "sync/atomic"
|
|
|
|
var (
|
|
mainTask *Task
|
|
liveTasks uint32
|
|
mainExitedByGoexit uint32
|
|
)
|
|
|
|
func addLiveTask(t *Task) {
|
|
if mainTask == nil {
|
|
mainTask = t
|
|
}
|
|
atomic.AddUint32(&liveTasks, 1)
|
|
}
|
|
|
|
// Exit exits the current task because runtime.Goexit was called.
|
|
func Exit() {
|
|
exit(true)
|
|
}
|
|
|
|
func exit(goexit bool) {
|
|
t := Current()
|
|
remaining := atomic.AddUint32(&liveTasks, ^uint32(0))
|
|
if t == mainTask {
|
|
if goexit {
|
|
if remaining == 0 {
|
|
runtimeFatal("all goroutines are asleep - deadlock!")
|
|
}
|
|
atomic.StoreUint32(&mainExitedByGoexit, 1)
|
|
}
|
|
} else if atomic.LoadUint32(&mainExitedByGoexit) != 0 && remaining == 0 {
|
|
runtimeFatal("all goroutines are asleep - deadlock!")
|
|
}
|
|
|
|
// TODO: explicitly free the stack after switching back to the scheduler.
|
|
Pause()
|
|
runtimeFatal("unreachable")
|
|
}
|