Skip to content

Non-deterministic fatal go runtime crashes on macOS #60

Description

@tsandall

Hi there!

I'm running into some non-deterministic go runtime crashes on macOS w/ v0.23.0. Here's an example:

package main

import (
	"fmt"

	"github.com/bytecodealliance/wasmtime-go"

	_ "github.com/bytecodealliance/wasmtime-go/build/include"        // to include the C headers.
	_ "github.com/bytecodealliance/wasmtime-go/build/linux-x86_64"   // to include the static lib for linking.
	_ "github.com/bytecodealliance/wasmtime-go/build/macos-x86_64"   // to include the static lib for linking.
	_ "github.com/bytecodealliance/wasmtime-go/build/windows-x86_64" // to include the static lib for linking.
)

func main() {

	bs, err := wasmtime.Wat2Wasm(`
	(module
		(func (export "f1")
			(unreachable)))
	`)
	check(err)

	for i := 0; ; i++ {
		fmt.Println("i:", i)
		store := wasmtime.NewStore(wasmtime.NewEngine())

		module, err := wasmtime.NewModule(store.Engine, bs)
		check(err)

		instance, err := wasmtime.NewInstance(store, module, nil)
		check(err)

		_, err = instance.GetExport("f1").Func().Call()
		if err == nil {
			panic("expected error")
		}
	}

}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

If you run this program on macOS, it should crash eventually (the last couple runs on my laptop took about 150 iterations, but it's not consistent).

It seems like something nasty is happening in the runtime when the unreachable instruction is executed.

Here's the output from the last run:

$ go run -mod=vendor main.go
i: 0
i: 1
<--------------8< snip snip 8<----------------->
i: 296
signal 16 received but handler not on signal stack
fatal error: non-Go code set up signal handler without SA_ONSTACK flag

runtime stack:
runtime: unexpected return pc for runtime.sigtramp called from 0xc000127c28
stack: frame={sp:0xc0001277b0, fp:0xc0001277c0} stack=[0xc00011f6e0,0xc000127ae0)
000000c0001276b0:  000000c0001276d0  0000000004049665 <runtime.sigNotOnStack+133>
000000c0001276c0:  0000000004c15568  0000000000000039
000000c0001276d0:  000000c000127728  00000000040483db <runtime.adjustSignalStack+411>
000000c0001276e0:  0000000000000010  000000c0001276f8
000000c0001276f0:  000000c000127738  0000000008c22000
000000c000127700:  0000000000010000  0000000000000001
000000c000127710:  000000c00010a330  0000000004c15c30
000000c000127720:  0000000000000000  000000c0001277a0
000000c000127730:  0000000004048131 <runtime.sigtrampgo+369>  000000c000000010
000000c000127740:  0000000004e8aea0  000000c000127760
000000c000127750:  0000000000000000  0000000000000000
000000c000127760:  0000000000000000  0000000000000000
000000c000127770:  0000000000000000  0000000000000000
000000c000127780:  0000000000000000  000000c000000180
000000c000127790:  000000c000127c28  000000c000127c90
000000c0001277a0:  000000c0001277f0  0000000004067db3 <runtime.sigtramp+51>
000000c0001277b0: <0000000000000010 !000000c000127c28
000000c0001277c0: >000000c000127c90  000000c000127c90
000000c0001277d0:  d1560bb8e9a711de  000000000000013e
000000c0001277e0:  000000000000013d  0000000000000200
000000c0001277f0:  000000c000127800  00007fff6c4b05fd
000000c000127800:  000000c000127dd8  0000000000000000
000000c000127810:  0000000000000000  0000000000000000
000000c000127820:  00000000000000de  0000000037140000
000000c000127830:  000000000600a318  0000000004e8aea0
000000c000127840:  000000c000000180  0000000000000008
000000c000127850:  0000000006000108  0000000000000000
000000c000127860:  000000c000127dd8  000000c000127d48
000000c000127870:  0000000004beb8e0  0000000000003001
000000c000127880:  0000000000000018  0000000000000000
000000c000127890:  ffffffffffffffff  000000000000013e
000000c0001278a0:  000000000000013d  0000000000000200
000000c0001278b0:  000000000400ea3b <runtime.mallocgc+667>  0000000000000202
runtime.throw(0x4c15568, 0x39)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/panic.go:1116 +0x72
runtime.sigNotOnStack(0x10)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/signal_unix.go:926 +0x85
runtime.adjustSignalStack(0xc000000010, 0x4e8aea0, 0xc000127760, 0x0)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/signal_unix.go:516 +0x19b
runtime.sigtrampgo(0x10, 0xc000127c28, 0xc000127c90)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/signal_unix.go:461 +0x171
runtime: unexpected return pc for runtime.sigtramp called from 0xc000127c28
stack: frame={sp:0xc0001277b0, fp:0xc0001277c0} stack=[0xc00011f6e0,0xc000127ae0)
000000c0001276b0:  000000c0001276d0  0000000004049665 <runtime.sigNotOnStack+133>
000000c0001276c0:  0000000004c15568  0000000000000039
000000c0001276d0:  000000c000127728  00000000040483db <runtime.adjustSignalStack+411>
000000c0001276e0:  0000000000000010  000000c0001276f8
000000c0001276f0:  000000c000127738  0000000008c22000
000000c000127700:  0000000000010000  0000000000000001
000000c000127710:  000000c00010a330  0000000004c15c30
000000c000127720:  0000000000000000  000000c0001277a0
000000c000127730:  0000000004048131 <runtime.sigtrampgo+369>  000000c000000010
000000c000127740:  0000000004e8aea0  000000c000127760
000000c000127750:  0000000000000000  0000000000000000
000000c000127760:  0000000000000000  0000000000000000
000000c000127770:  0000000000000000  0000000000000000
000000c000127780:  0000000000000000  000000c000000180
000000c000127790:  000000c000127c28  000000c000127c90
000000c0001277a0:  000000c0001277f0  0000000004067db3 <runtime.sigtramp+51>
000000c0001277b0: <0000000000000010 !000000c000127c28
000000c0001277c0: >000000c000127c90  000000c000127c90
000000c0001277d0:  d1560bb8e9a711de  000000000000013e
000000c0001277e0:  000000000000013d  0000000000000200
000000c0001277f0:  000000c000127800  00007fff6c4b05fd
000000c000127800:  000000c000127dd8  0000000000000000
000000c000127810:  0000000000000000  0000000000000000
000000c000127820:  00000000000000de  0000000037140000
000000c000127830:  000000000600a318  0000000004e8aea0
000000c000127840:  000000c000000180  0000000000000008
000000c000127850:  0000000006000108  0000000000000000
000000c000127860:  000000c000127dd8  000000c000127d48
000000c000127870:  0000000004beb8e0  0000000000003001
000000c000127880:  0000000000000018  0000000000000000
000000c000127890:  ffffffffffffffff  000000000000013e
000000c0001278a0:  000000000000013d  0000000000000200
000000c0001278b0:  000000000400ea3b <runtime.mallocgc+667>  0000000000000202
runtime.sigtramp(0xc000127c90, 0xc000127c90, 0xd1560bb8e9a711de, 0x13e, 0x13d, 0x200, 0xc000127800, 0x7fff6c4b05fd, 0xc000127dd8, 0x0, ...)
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/sys_darwin_amd64.s:229 +0x33

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
	/usr/local/Cellar/go/1.15.8/libexec/src/runtime/asm_amd64.s:1374 +0x1 fp=0xc000066fe8 sp=0xc000066fe0 pc=0x4066481

goroutine 1 [running]:
	goroutine running on other thread; stack unavailable
exit status 2

I'm running go1.15.8 after I found the other issues related to older versions (<1.14.11, I think).

One other data point/question...

I've found that if a Go-defined function is called and panics before the unreachable instruction is executed, I still run into the same crash. For example, here's the WAT:

		(import "" "f2" (func $f2))
		(func (export "f1")
			(call $f2)
			(unreachable)))

In this case, the Go-defined function "f2" just calls panic().

I'm on macOS 10.15.7 in case that helps.

Would rewriting my Go-defined functions to use Traps instead of panicking help at all?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions