go version)?$ go version go version go1.14.1 darwin/amd64
Yes
go env)?go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/hajimehoshi/Library/Caches/go-build"
GOENV="/Users/hajimehoshi/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/hajimehoshi/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/ht/ky_bwgzs4bd5z1hh02k34x_h0000gn/T/go-build937690981=/tmp/go-build -gno-record-gcc-switches -fno-common"
Build this Go program as Wasm and run it on a browser several times:
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
ch3 := make(chan struct{})
go func() {
for {
time.Sleep(5 * time.Millisecond)
ch1 <- "A"
}
}()
go func() {
for {
time.Sleep(7 * time.Millisecond)
ch2 <- "B"
}
}()
go func() {
for {
time.Sleep(3 * time.Second)
close(ch3)
}
}()
loop:
for {
select {
case str := <-ch1:
fmt.Println(str)
case str := <-ch2:
fmt.Println(str)
case <-ch3:
fmt.Println("Done")
break loop
}
}
}
No error (except for 'already exit')
Sometimes I saw this error:
Uncaught RuntimeError: memory access out of bounds
at runtime.__waitq_.dequeue (wasm-function[113]:0xbe09)
at runtime.chanrecv (wasm-function[109]:0xab34)
at runtime.chanrecv1 (wasm-function[108]:0xa89b)
at syscall.fsCall (wasm-function[1636]:0x12510e)
at syscall.Write (wasm-function[1634]:0x12471b)
at internal_poll.__FD_.Write (wasm-function[1657]:0x128d1e)
at os.__File_.Write (wasm-function[1669]:0x129ef2)
at fmt.Fprintln (wasm-function[1700]:0x131eb1)
at main.main (wasm-function[1720]:0x14065c)
at wasm_pc_f_loop (wasm-function[950]:0xc3a5f)
| runtime.__waitq_.dequeue | @ | 008b857e-113:116
聽 | runtime.chanrecv | @ | 008b857e-109:249
聽 | runtime.chanrecv1 | @ | 008b857e-108:37
聽 | syscall.fsCall | @ | 008b857e-1636:354
聽 | syscall.Write | @ | 008b857e-1634:451
聽 | internal_poll.__FD_.Write | @ | 008b857e-1657:385
聽 | os.__File_.Write | @ | 008b857e-1669:164
聽 | fmt.Fprintln | @ | 008b857e-1700:170
聽 | main.main | @ | 008b857e-1720:471
聽 | wasm_pc_f_loop | @ | 008b857e-950:14
聽 | wasm_export_resume | @ | 008b857e-949:5
聽 | _resume | @ | wasm_exec.js:544
聽 | (anonymous) | @ | wasm_exec.js:308
聽 | setTimeout (async) | 聽 | 聽
聽 | runtime.scheduleTimeoutEvent | @ | wasm_exec.js:306
聽 | runtime.scheduleTimeoutEvent | @ | 008b857e-969:6
聽 | runtime.beforeIdle | @ | 008b857e-158:107
聽 | runtime.findrunnable | @ | 008b857e-564:1278
聽 | runtime.schedule | @ | 008b857e-569:960
聽 | runtime.park_m | @ | 008b857e-572:245
聽 | runtime.mcall | @ | 008b857e-899:77
聽 | runtime.gopark | @ | 008b857e-515:312
聽 | runtime.selectgo | @ | 008b857e-655:2335
聽 | main.main | @ | 008b857e-1720:349
聽 | wasm_pc_f_loop | @ | 008b857e-950:14
聽 | wasm_export_resume | @ | 008b857e-949:5
聽 | _resume | @ | wasm_exec.js:544
聽 | (anonymous) | @ | wasm_exec.js:308
...
CC @neelance
I could not confirm this issue on node.js, but could confirm on Chrome browser (Version 80.0.3987.149 (Official Build) (64-bit))
CC @dmitshur
Any updates?
I can also reproduce it. It seems y.prev in runtime.(*waitq).dequeue is pointing to some garbage, a huge number beyond the address space. And it is also reproducible without the second channel (ch2), with a different error where it panics in with nil channel in chanrecv, called from syscall.fsCall. This channel is clearly non-nil, as it is created a few lines ago. Looks like some kind of memory corruption to me. I haven't figured out the cause, though.
This doesn't happen with Go 1.13.9. I think this is a regression. I'll try to bisect.
6becb033341602f2df9d7c55cc23e64b925bbee2 seems the culprit: from this commit, I saw an error, which is different from the original error though:
fatal error: unexpected signal during runtime execution
wasm_exec.js:47
runtime stack:
wasm_exec.js:47 runtime: unexpected return pc for syscall.fsCall called from 0x160258670d0f8fc0
wasm_exec.js:47 stack: frame={sp:0x156ac0, fp:0x156b58} stack=[0x154fd8,0x156bd8)
wasm_exec.js:47 00000000001569c0: 0000000000038ab1 000000000000002a
wasm_exec.js:47 00000000001569d0: 000000000013bbc0 0000000010bf0003 <runtime.typedmemmove+3>
wasm_exec.js:47 00000000001569e0: 0000000000000001 160258670ca48400
wasm_exec.js:47 00000000001569f0: 0000000000000001 000000000042c360
wasm_exec.js:47 0000000000156a00: 000000000042c3b0 000000001057001a <runtime.chanrecv+26>
wasm_exec.js:47 0000000000156a10: 0000000000000000 0000000000156b38
wasm_exec.js:47 0000000000156a20: 0000000000000007 0000000013240000 <runtime.(*mheap).coalesce.func2+0>
wasm_exec.js:47 0000000000156a30: 0000000010880010 <runtime.beforeIdle+16> 0000000000000000
wasm_exec.js:47 0000000000156a40: 0000000000000002 0000000000000007
wasm_exec.js:47 0000000000156a50: 000000000046b9c0 0000000000000001
wasm_exec.js:47 0000000000156a60: 1602586700000001 160258670d0f8fc0
wasm_exec.js:47 0000000000156a70: 0000000000161800 0000000000410058
wasm_exec.js:47 0000000000156a80: 0000000000000000 0000000000000001
wasm_exec.js:47 0000000000156a90: 0000000010560002 <runtime.chanrecv1+2> 0000000000410000
wasm_exec.js:47 0000000000156aa0: 0000000000156b38 0000000000000001
wasm_exec.js:47 0000000000156ab0: 0000000011e60010 <runtime.casgstatus+16> 000000001626000d <syscall.fsCall+13>
wasm_exec.js:47 0000000000156ac0: <0000000000410000 0000000000156b38
wasm_exec.js:47 0000000000156ad0: 000000000042c360 0000000100000001
wasm_exec.js:47 0000000000156ae0: 0000000100000000 000000000042c3b0
wasm_exec.js:47 0000000000156af0: 0000000000000000 00000000004105d8
wasm_exec.js:47 0000000000156b00: 1602586700000007 0000000000410000
wasm_exec.js:47 0000000000156b10: 0000000200000001 000000000013bbc0
wasm_exec.js:47 0000000000156b20: 160258670cc8d600 0000000000410000
wasm_exec.js:47 0000000000156b30: 000000001209005e <runtime.schedule+94> 0000000000000000
wasm_exec.js:47 0000000000156b40: 0000000000000000 0000000000000000
wasm_exec.js:47 0000000000156b50: !160258670d0f8fc0 >0000000012ed0000 <runtime.isSystemGoroutine+0>
wasm_exec.js:47 0000000000156b60: 0000000000400900 0000000000000000
wasm_exec.js:47 0000000000156b70: 0000000000000000 000000000013bbc0
wasm_exec.js:47 0000000000156b80: 0000000010590004 <runtime.chanparkcommit+4> 000000000042e0b8
wasm_exec.js:47 0000000000156b90: 00000000120c001b <runtime.park_m+27> 0000000000400900
wasm_exec.js:47 0000000000156ba0: 000000000042e0b8 0000000000000001
wasm_exec.js:47 0000000000156bb0: 000000000013bbc0 00000000134d0001 <runtime.mcall+1>
wasm_exec.js:47 0000000000156bc0: 0000000000400900 0000000000156c00
wasm_exec.js:47 0000000000156bd0: 0100000000000000
wasm_exec.js:47 syscall.fsCall(0x12ed0000, 0x400900, 0x0, 0x0, 0x13bbc0, 0x10590004, 0x42e0b8, 0x120c001b)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/syscall/fs_js.go:513 +0xd
wasm_exec.js:47
wasm_exec.js:47 goroutine 1 [waiting]:
wasm_exec.js:47 syscall/js.Value.Call(0x7ff800000000000a, 0x32e54, 0x5, 0x452000, 0x6, 0xa, 0x5)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/syscall/js/js.go:326 +0x3
wasm_exec.js:47 syscall.fsCall(0x32e54, 0x5, 0x436cb8, 0x5, 0x5, 0x44e001, 0x430a90, 0x41e008)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/syscall/fs_js.go:496 +0xc
wasm_exec.js:47 syscall.Write(0x1, 0x41e008, 0x2, 0x8, 0x1440000e, 0x12da18, 0x0)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/syscall/fs_js.go:417 +0x11
wasm_exec.js:47 internal/poll.(*FD).Write(0x42c120, 0x41e008, 0x2, 0x8, 0x0, 0x0, 0x0)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/internal/poll/fd_unix.go:268 +0x22
wasm_exec.js:47 os.(*File).write(...)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/os/file_unix.go:276
wasm_exec.js:47 os.(*File).Write(0x40c020, 0x41e008, 0x2, 0x8, 0x436e18, 0x13410000, 0x10770005)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/os/file.go:153 +0xf
wasm_exec.js:47 fmt.Fprintln(0x4a200, 0x40c020, 0x436ec8, 0x1, 0x1, 0x13a20, 0x156c08, 0x0)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/fmt/print.go:265 +0x8
wasm_exec.js:47 fmt.Println(...)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/fmt/print.go:274
wasm_exec.js:47 main.main()
wasm_exec.js:47 /Users/hajimehoshi/test/wasmbug/main.go:38 +0xf
wasm_exec.js:47
wasm_exec.js:47 goroutine 6 [chan send]:
wasm_exec.js:47 main.main.func1(0x42e060)
wasm_exec.js:47 /Users/hajimehoshi/test/wasmbug/main.go:16 +0x4
wasm_exec.js:47 created by main.main
wasm_exec.js:47 /Users/hajimehoshi/test/wasmbug/main.go:13 +0x5
wasm_exec.js:47
wasm_exec.js:47 goroutine 7 [sleep]:
wasm_exec.js:47 time.Sleep(0x6acfc0)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/runtime/time.go:247 +0xe
wasm_exec.js:47 main.main.func2(0x42e0c0)
wasm_exec.js:47 /Users/hajimehoshi/test/wasmbug/main.go:21 +0x3
wasm_exec.js:47 created by main.main
wasm_exec.js:47 /Users/hajimehoshi/test/wasmbug/main.go:19 +0x6
wasm_exec.js:47
wasm_exec.js:47 goroutine 8 [sleep]:
wasm_exec.js:47 time.Sleep(0xb2d05e00)
wasm_exec.js:47 /Users/hajimehoshi/go-code/src/runtime/time.go:247 +0xe
wasm_exec.js:47 main.main.func3(0x42e120)
wasm_exec.js:47 /Users/hajimehoshi/test/wasmbug/main.go:27 +0x3
wasm_exec.js:47 created by main.main
wasm_exec.js:47 /Users/hajimehoshi/test/wasmbug/main.go:25 +0x7
After 6becb033341602f2df9d7c55cc23e64b925bbee2, c2e2296dd7dea68de4a45d8dc82b1920130eb74a is the first commit to see the same error as reported.
CC @ianlancetaylor
I think that somebody familiar with wasm is going to have to dig into this. My contribution here is https://golang.org/cl/171827 and https://golang.org/cl/203890. It sounds like the new timers have broken some garbage collection invariant, but I don't know what it would be. Sorry.
Thanks @hajimehoshi and @ianlancetaylor ! I could probably look into this a little more, but maybe not today. I'm having some issue running wasm on my browser...
@cherrymui Hi, what's going on this? Thanks.
This is the same issue as #38574, please see my analysis there.
Change https://golang.org/cl/230178 mentions this issue: runtime: fix race condition between timer and event handler
Thanks.
I was wondering if this will be backported to 1.14 or not since this is a memory-corruption error.
@hajimehoshi Seems unlikely, because js/wasm is still experimental. See https://github.com/golang/go/wiki/MinorReleases for the policy on backports.
Ah OK, that's unfortunate but makes sense. Thanks!
Most helpful comment
I can also reproduce it. It seems
y.previnruntime.(*waitq).dequeueis pointing to some garbage, a huge number beyond the address space. And it is also reproducible without the second channel (ch2), with a different error where it panics in with nil channel inchanrecv, called fromsyscall.fsCall. This channel is clearly non-nil, as it is created a few lines ago. Looks like some kind of memory corruption to me. I haven't figured out the cause, though.