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: all goroutines asleep and no JavaScript callback pending - deadlock #26382

Closed
bradfitz opened this issue Jul 14, 2018 · 20 comments
Labels
arch-wasm WebAssembly issues FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@bradfitz
Copy link
Contributor

I've seen a few trybot flakes on wasm like:

https://storage.googleapis.com/go-build-log/fd762fcb/js-wasm_280bcf2c.log (from wasm-unrelated https://go-review.googlesource.com/c/go/+/123779)

ok  	math/bits	1.768s
ok  	math/cmplx	1.762s
ok  	math/rand	4.233s
ok  	mime	1.705s
ok  	mime/multipart	6.236s
ok  	mime/quotedprintable	3.097s
ok  	net	2.596s
error: all goroutines asleep and no JavaScript callback pending - deadlock!
FAIL	net/http	15.608s
2018/07/13 22:17:40 Failed: exit status 1

@bradfitz bradfitz added NeedsFix The path to resolution is known, but the work has not been done. arch-wasm WebAssembly issues labels Jul 14, 2018
@bradfitz bradfitz added this to the Go1.11 milestone Jul 14, 2018
@gopherbot
Copy link

Change https://golang.org/cl/123936 mentions this issue: syscall/js: show goroutine stack traces on deadlock

gopherbot pushed a commit that referenced this issue Jul 19, 2018
When using callbacks, it is not necessarily a deadlock if there is no
runnable goroutine, since a callback might still be pending. If there
is no callback pending, Node.js simply exits with exit code zero,
which is not desired if the Go program is still considered running.
This is why an explicit check on exit is used to trigger the "deadlock"
error. This CL makes it so this is Go's normal "deadlock" error, which
includes the stack traces of all goroutines.

Updates #26382

Change-Id: If88486684d0517a64f570009a5ea0ad082679a54
Reviewed-on: https://go-review.googlesource.com/123936
Run-TryBot: Richard Musiol <neelance@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
@neelance
Copy link
Member

@bradfitz Please post a link here if you see it happening again, so I can check the stack traces.

@xudongzheng
Copy link
Contributor

I think I ran into the same issue with https://play.golang.org/p/Ymt6QgfYH93. Not sure if I'm underestimating the complexity of the fix.

@gopherbot
Copy link

Change https://golang.org/cl/127515 mentions this issue: syscall/js: run callback function in goroutine

@neelance
Copy link
Member

neelance commented Aug 2, 2018

@xudongzheng Your issue is unrelated to the flake above. Please see https://tip.golang.org/pkg/syscall/js/#NewCallback on why it happens.

@andybons andybons modified the milestones: Go1.11, Go1.11.1 Aug 25, 2018
@kaskavalci
Copy link

I get this error when I'm doing a http request within a callback function. Apparently RoundTrip function hangs while waiting for an answer. Network tab in browser shows successful request and response correctly.

fatal error: all goroutines are asleep - deadlock!
VM5521 wasm_exec.js:45 
VM5521 wasm_exec.js:45 goroutine 1 [chan receive]:
VM5521 wasm_exec.js:45 main.main()
VM5521 wasm_exec.js:45 	/Users/kaskavalci/gow/test/wasm/main.go:117 +0x11
VM5521 wasm_exec.js:45 
VM5521 wasm_exec.js:45 goroutine 5 [select]:
VM5521 wasm_exec.js:45 net/http.(*Transport).RoundTrip(0x467860, 0xc0b4400, 0x0, 0x0, 0x0)
VM5521 wasm_exec.js:45 	/usr/local/Cellar/go/1.11/libexec/src/net/http/roundtrip_js.go:149 +0x44

@agnivade
Copy link
Contributor

@kaskavalci - You have successfully repeated the issue in #26382 (comment). See the comment above.

@kaskavalci
Copy link

Oh 🤦‍♂️
For someone who is looking for a quick answer, just wrap your request in a go-routine because

A blocking callback should therefore explicitly start a new goroutine.

example := func(i []js.Value) {
	go func() {
		fmt.Println(http.Get("http://localhost:9276/"))
	}()
}
js.Global().Set("example", js.NewCallback(example))
select {}

@FiloSottile FiloSottile modified the milestones: Go1.11.1, Go1.12 Aug 31, 2018
@FiloSottile
Copy link
Contributor

@gopherbot please file this to be considered for backport to 1.11.

@gopherbot
Copy link

Backport issue(s) opened: #27425 (for 1.11).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases.

@neelance
Copy link
Member

@bradfitz Is there a way to search the trybot logs for this flake?

@josharian
Copy link
Contributor

@neelance
Copy link
Member

According to the logs, the last time this happened was on 2018/07/19. I'd say we can close this.

@danaugrs
Copy link

danaugrs commented Sep 22, 2019

I'm getting a similar error after upgrading from Go 1.12 to 1.13:

fatal error: all goroutines are asleep - deadlock!

even though there should be a callback (requestAnimationFrame) pending.

@FiloSottile
Copy link
Contributor

@danaugrs Please open a new issue, we don't track closed issues, and that's a pretty generic error.

@danaugrs
Copy link

@FiloSottile I figured it out, the problem was reading from the channel of a time.Timer inside the requestAnimationFrame callback. The behavior must have changed from 1.12 to 1.13 but I'm not sure which is correct. I'll open an issue if it turns out to be a blocker for me.

@WeiChieh-Chen
Copy link

if use goroutine, how return value to frontend ?

@loeffel-io
Copy link

this still happens to me with go version go1.17 darwin/amd64

package main

import (
	"io/ioutil"
	"log"
	"net/http"
	"syscall/js"
)

func add(this js.Value, args []js.Value) interface{} {
	resp, err := http.Get("https://jsonplaceholder.typicode.com/posts")
	if err != nil {
		log.Fatalln(err)
	}
	//We Read the response body on the line below.
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalln(err)
	}
	//Convert the body to type string
	sb := string(body)
	log.Printf(sb)

	return nil
}

func main() {
	c := make(chan struct{}, 0)
	js.Global().Set("add", js.FuncOf(add))
	<-c
}

result: #26382 (comment)

running this in a goroutine works:

package main

import (
	"io/ioutil"
	"log"
	"net/http"
	"syscall/js"
)

func add(this js.Value, args []js.Value) interface{} {
	go func() {
		resp, err := http.Get("https://jsonplaceholder.typicode.com/posts")
		if err != nil {
			log.Fatalln(err)
		}
		//We Read the response body on the line below.
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Fatalln(err)
		}
		//Convert the body to type string
		sb := string(body)
		log.Printf(sb)
	}()

	return nil
}

func main() {
	c := make(chan struct{}, 0)
	js.Global().Set("add", js.FuncOf(add))
	<-c
}

@neelance
Copy link
Member

@loeffel-io Your issue is unrelated to the flake above. Please see https://pkg.go.dev/syscall/js@master#FuncOf on why it happens.

@loeffel-io
Copy link

My fault - thanks! @neelance

@golang golang locked and limited conversation to collaborators Jun 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
arch-wasm WebAssembly issues FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests