mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-13 07:23:39 +00:00
runtime: make fatal failures unrecoverable
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.
This commit is contained in:
+36
-8
@@ -993,15 +993,15 @@ func TestGoexitCrash(t *testing.T) {
|
||||
name string
|
||||
want string
|
||||
}{
|
||||
{"main", "all goroutines are asleep - deadlock!"},
|
||||
{"deadlock", "all goroutines are asleep - deadlock!"},
|
||||
{"exit", "all goroutines are asleep - deadlock!"},
|
||||
{"main-other", "all goroutines are asleep - deadlock!"},
|
||||
{"in-panic", "all goroutines are asleep - deadlock!"},
|
||||
{"main", "fatal error: all goroutines are asleep - deadlock!"},
|
||||
{"deadlock", "fatal error: all goroutines are asleep - deadlock!"},
|
||||
{"exit", "fatal error: all goroutines are asleep - deadlock!"},
|
||||
{"main-other", "fatal error: all goroutines are asleep - deadlock!"},
|
||||
{"in-panic", "fatal error: all goroutines are asleep - deadlock!"},
|
||||
{"panic", "panic: panic after Goexit"},
|
||||
{"recovered-panic", "all goroutines are asleep - deadlock!"},
|
||||
{"recover-before-panic", "all goroutines are asleep - deadlock!"},
|
||||
{"recover-before-panic-loop", "all goroutines are asleep - deadlock!"},
|
||||
{"recovered-panic", "fatal error: all goroutines are asleep - deadlock!"},
|
||||
{"recover-before-panic", "fatal error: all goroutines are asleep - deadlock!"},
|
||||
{"recover-before-panic-loop", "fatal error: all goroutines are asleep - deadlock!"},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
output := &bytes.Buffer{}
|
||||
@@ -1022,6 +1022,34 @@ func TestGoexitCrash(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuntimeFatal(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
options := optionsFromTarget("", sema)
|
||||
config, err := builder.NewConfig(&options)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
output := &bytes.Buffer{}
|
||||
_, err = buildAndRun("testdata/runtimefatal.go", config, output, nil, nil, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||
cmd.Stdout = nil
|
||||
cmd.Stderr = nil
|
||||
data, err := cmd.CombinedOutput()
|
||||
output.Write(data)
|
||||
return err
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("program unexpectedly exited successfully")
|
||||
}
|
||||
if want := "fatal error: sync: unlock of unlocked Mutex"; !strings.Contains(output.String(), want) {
|
||||
t.Fatalf("output does not contain %q:\n%s", want, output.String())
|
||||
}
|
||||
if strings.Contains(output.String(), "recovered:") {
|
||||
t.Fatalf("fatal runtime error was recovered:\n%s", output.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestTest(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user