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

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

Closed
darkLord19 opened this issue Sep 10, 2020 · 4 comments
Closed

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

darkLord19 opened this issue Sep 10, 2020 · 4 comments

Comments

@darkLord19
Copy link
Contributor

@darkLord19 darkLord19 commented Sep 10, 2020

What version of Go are you using (go version)?

$ go version
go version go1.15 darwin/amd64

Does this issue reproduce with the latest release?

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/uparmar/Library/Caches/go-build"
GOENV="/Users/uparmar/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/uparmar/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/uparmar/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.15/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.15/libexec/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/l7/x5hcvngd5m99k62kxv7srrdr0000gn/T/go-build448055941=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Call Go function from js(from chrome dev tools console)

// +build js, wasm

package main

import (
	"net/http"
	"syscall/js"
)

func test(this js.Value, args []js.Value) interface{} {
	println("test called")
	resp, err := http.Get("https://hacker-news.firebaseio.com/v0/item/24429478.json")
	if err != nil {
		println(err.Error())
		return nil
	}
	defer resp.Body.Close()
	var tmp []byte
	resp.Body.Read(tmp)
	println("response is", tmp)
	return nil
}

func registerFuncs() {
	js.Global().Set("test", js.FuncOf(test))
}

func main() {
	c := make(chan struct{})
	println("WASM Go Initialized")
	registerFuncs()
	<-c
}

<!doctype html>
<html>

<head>
	<meta charset="utf-8">
	<title>Test</title>
</head>

<body>
	<h1> TEST </h1>
</body>

<footer>
	<script type="text/javascript" src="./wasm_exec.js"></script>
	<script>
		if (!WebAssembly.instantiateStreaming) { // polyfill
			WebAssembly.instantiateStreaming = async (resp, importObject) => {
				const source = await (await resp).arrayBuffer();
				return await WebAssembly.instantiate(source, importObject);
			};
		}

		const go = new Go();
		let mod, inst;
		WebAssembly.instantiateStreaming(fetch("test.wasm"), go.importObject).then(
		async result => {
			mod = result.module;
			inst = result.instance;
                        go.run(inst)
		}).catch((err) => {
			console.error(err);
		});
	</script>

</footer>

</html>

What did you expect to see?

Function running succesfully

What did you see instead?

test()
wasm_exec.js:50 test called
wasm_exec.js:50 fatal error: all goroutines are asleep - deadlock!
wasm_exec.js:50 
wasm_exec.js:50 goroutine 1 [chan receive]:
wasm_exec.js:50 main.main()
wasm_exec.js:50 	/Users/uparmar/Development/test_wasm/test.go:33 +0x7
wasm_exec.js:50 
wasm_exec.js:50 goroutine 6 [select]:
wasm_exec.js:50 net/http.(*Transport).RoundTrip(0x33c860, 0x486000, 0x33c860, 0x0, 0x0)
wasm_exec.js:50 	/usr/local/Cellar/go/1.15/libexec/src/net/http/roundtrip_js.go:168 +0x55
wasm_exec.js:50 net/http.send(0x486000, 0xc8260, 0x33c860, 0x0, 0x0, 0x0, 0x0, 0x40c040, 0x424ab0, 0x1)
wasm_exec.js:50 	/usr/local/Cellar/go/1.15/libexec/src/net/http/client.go:252 +0x5b
wasm_exec.js:50 net/http.(*Client).send(0x3490c0, 0x486000, 0x0, 0x0, 0x0, 0x40c040, 0x0, 0x1, 0xf8)
wasm_exec.js:50 	/usr/local/Cellar/go/1.15/libexec/src/net/http/client.go:176 +0x13
wasm_exec.js:50 net/http.(*Client).do(0x3490c0, 0x486000, 0x0, 0x0, 0x0)
wasm_exec.js:50 	/usr/local/Cellar/go/1.15/libexec/src/net/http/client.go:718 +0x38
wasm_exec.js:50 net/http.(*Client).Do(...)
wasm_exec.js:50 	/usr/local/Cellar/go/1.15/libexec/src/net/http/client.go:586
wasm_exec.js:50 net/http.(*Client).Get(0x3490c0, 0x8c00d, 0x38, 0x41a138, 0x14a30008, 0x14a80007)
wasm_exec.js:50 	/usr/local/Cellar/go/1.15/libexec/src/net/http/client.go:475 +0xe
wasm_exec.js:50 net/http.Get(...)
wasm_exec.js:50 	/usr/local/Cellar/go/1.15/libexec/src/net/http/client.go:447
wasm_exec.js:50 main.test(0x0, 0x0, 0x368070, 0x0, 0x0, 0x0, 0x0)
wasm_exec.js:50 	/Users/uparmar/Development/test_wasm/test.go:12 +0x7
wasm_exec.js:50 syscall/js.handleEvent()
wasm_exec.js:50 	/usr/local/Cellar/go/1.15/libexec/src/syscall/js/func.go:96 +0x24
wasm_exec.js:141 exit code: 2
@agnivade
Copy link
Contributor

@agnivade agnivade commented Sep 10, 2020

This is documented here: https://golang.org/pkg/syscall/js/#FuncOf

As a consequence, if one wrapped function blocks, JavaScript's event loop is blocked until that function returns. Hence, calling any async JavaScript API, which requires the event loop, like fetch (http.Client), will cause an immediate deadlock. Therefore a blocking function should explicitly start a new goroutine.

You would need to perform the http.Get in a separate goroutine.

@darkLord19 darkLord19 closed this Sep 10, 2020
@darkLord19
Copy link
Contributor Author

@darkLord19 darkLord19 commented Sep 10, 2020

Thanks @agnivade for clarification.

@darkLord19
Copy link
Contributor Author

@darkLord19 darkLord19 commented Sep 12, 2020

@agnivade I am doing http.Get in seperate routine but still getting error. I am creating a channel before invoking go routine to perform http.Get and writing on it from inside the go routine and reading from channel later down the function. Is this also a limitation?

@agnivade
Copy link
Contributor

@agnivade agnivade commented Sep 13, 2020

Yes, that does not change anything if you read from the channel in the same function. It will still cause the deadlock. You have to create a separate event handler loop or some other mechanism to make http requests and read responses.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.