Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasm: fatal error: all goroutines are asleep - deadlock! #34478

Closed
danaugrs opened this issue Sep 23, 2019 · 7 comments
Closed

wasm: fatal error: all goroutines are asleep - deadlock! #34478

danaugrs opened this issue Sep 23, 2019 · 7 comments
Labels
arch-wasm WebAssembly issues FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@danaugrs
Copy link

Version: go1.13 windows/amd64
Does this issue reproduce with the latest release? Yes

go env Output
set GO111MODULE=
set GOARCH=wasm
set GOBIN=
set GOCACHE=C:\Users\danau\AppData\Local\go-build
set GOENV=C:\Users\danau\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GONOPROXY=
set GONOSUMDB=
set GOOS=js
set GOPATH=C:\projects\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=c:\go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=c:\go\pkg\tool\windows_amd64
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\danau\AppData\Local\Temp\go-build158127038=/tmp/go-build -gno-record-gcc-switches

Minimal Reproducible Example

package main

import (
	"fmt"
	"syscall/js"
)

func doStuffSynchronously() {
	done := make(chan bool)
	f := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		fmt.Println("DOING STUFF")
		done <- true
		return nil
	})
	defer f.Release()
	js.Global().Call("setTimeout", f, 1000)
	<-done
	fmt.Println("DONE DOING STUFF")
}

func main() {
	
	doStuffSynchronously() // <- WORKS HERE

	cb := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		fmt.Println("CB CALLED")
		doStuffSynchronously() // <- CRASHES WITH "fatal error: all goroutines are asleep - deadlock!"
		return nil
	})
	defer cb.Release()
	js.Global().Call("setTimeout", cb, 1000)

	// Prevent app from finishing while we wait for callback to execute
	neverDone := make(chan bool)
	<-neverDone
}

What did you expect to see?

I expected doStuffSynchronously() to work inside a callback just like it works outside one.

What did you see instead?

fatal error: all goroutines are asleep - deadlock!

@cherrymui
Copy link
Member

As https://golang.org/pkg/syscall/js/#FuncOf says:

Blocking operations in the wrapped function will block the event loop. As a consequence, if one wrapped function blocks, other wrapped funcs will not be processed. A blocking function should therefore explicitly start a new goroutine.

currently, blocking operation, such as channel send, doesn't work in callbacks.

@danaugrs
Copy link
Author

danaugrs commented Sep 23, 2019

@cherrymui Thanks for the fast reply! If I start a new goroutine go doStuffSynchronously() is it guaranteed that it will be executed sequentially (i.e. the go syntax is only necessary due to limitations in the WASM implementation)?

@cherrymui
Copy link
Member

I think it is not guaranteed to be executed sequentially, just like the go statement in general.

@danaugrs
Copy link
Author

danaugrs commented Sep 23, 2019

@cherrymui Yeah, just tried it and it's async - is there any workaround?

@agnivade
Copy link
Contributor

There is none at the moment. If you are making any call to JS land from inside a wrapped function, it's a deadlock. You have to change your programming model accordingly.

@bcmills
Copy link
Contributor

bcmills commented Sep 24, 2019

@cherrymui, @neelance: should we keep this issue open to track a future improvement to relax this restriction, or is it going to remain this way for the foreseeable future?

@bcmills bcmills added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Sep 24, 2019
@bcmills bcmills added this to the Unplanned milestone Sep 24, 2019
@neelance
Copy link
Member

@bcmills I don't see any way to relax this restriction. setTimeout can only fire its callback if the event loop continues to run. The documentation may get improved by #34324 (comment). Closing this issue.

@danaugrs Btw: You can use select {} instead of neverDone.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
arch-wasm WebAssembly issues FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

6 participants