~eliasnaur/gio#82: 
Webassembly Freezes in some cases

So I'm not sure where the root of this problem actually is, but what it comes down to is that if there is a request (Or possibly other long running task) in the event loop then webassembly will freeze. For example by adding

cl := &http.Client{}
    response, err := cl.Get("http://localhost:8080")
    if err != nil {
        log.Fatalf("%w", err)
    } else {
        defer response.Body.Close()
        contents, err := ioutil.ReadAll(response.Body)
        if err != nil {
            log.Fatalf("%w", err)
        }
        fmt.Printf("This is a test %s\n", string(contents))
    }

to line 124 in the kitchen example, i.e. the first thing the kitchen function does, then it works fine with go run . but won't work when compiled to webassembly. Scatter does a similar thing if you try and do the same request at line 1203, but in my experience webassembly will exit saying that all go routines are asleep. I admit that this might be a fundamental misunderstanding of the event loop on my part and having long running processes in there is maybe not ideal, but the fact that it work natively and fails for webassembly makes it very hard to debug. Please let me know if you need more info or where I should start in trying to debug it.

Status
REPORTED
Submitter
~rexfuzzle
Assigned to
No-one
Submitted
4 months ago
Updated
4 months ago
Labels
No labels applied.

~eliasnaur 4 months ago

On Wed Jan 22, 2020 at 06:36, ~rexfuzzle wrote:

So I'm not sure where the root of this problem actually is, but what it comes down to is that if there is a request (Or possibly other long running task) in the event loop then webpack will freeze. For example by adding cl := &http.Client{} response, err := cl.Get("http://localhost:8080") if err != nil { log.Fatalf("%w", err) } else { defer response.Body.Close() contents, err := ioutil.ReadAll(response.Body) if err != nil { log.Fatalf("%w", err) } fmt.Printf("This is a test %s\n", string(contents)) } to line 124 in the kitchen example, i.e. the first thing the kitchen function does, then it works fine with go run . but won't work when compiled to webpack. Scatter does a similar thing if you try and do the same request at line 1203, but in my experience webpack will exit saying that all go routines are asleep. I admit that this might be a fundamental misunderstanding of the event loop on my part and having long running processes in there is maybe not ideal, but the fact that it work natively and fails for webpack makes it very hard to debug. Please let me know if you need more info or where I should start in trying to debug it.

Excuse my ignorance, but I don't even know what webpack is, but your error message reminds me of

https://github.com/golang/go/issues/34478

If you can provide a minimal, complete and easily reproducible example I can take a look.

~theclapp 4 months ago

Webpack is a packager for web apps, so at a guess you're running this in a browser as webassembly?

First of all, running an http GET in the event loop is a terrible idea, webpack or not. Layout events can happen tens or even hundreds of times per second. Any kind of long running process should be in a separate goroutine.

This is just a guess, but I wouldn't be surprised if the http Client is not implemented in the webassembly code. So quite possibly your log.Fatalf is biting you. That's where I'd look first.

But also take that GET outside of the event loop.

~rexfuzzle 4 months ago

Sorry, I meant webassembly, not web pack- I corrected the post. I'll work on the smallest possible example and post it here when I've got one that errors every time.

I realise that this is a bad idea, but what is weird is that it works in some parts of the code for web assembly, but not others, i.e. if the http call is in the Event loop of one of the pages of the scatter example it seems to work, so that would tell me the http client is implemented. I've also tried with simple fmt.Println instead of the log which also didn't work. Anyway, here is the example: https://gist.github.com/grantstephens/da5f7f947a4edaec725c6c88fedf8f30 This gives me an error that looks like: fatal error: all goroutines are asleep - deadlock! wasm_exec.js:47:14 <empty string> wasm_exec.js:47:14 goroutine 1 [chan receive]: wasm_exec.js:47:14 gioui.org/app/internal/window.Main(...)

~eliasnaur 4 months ago

On Wed Jan 22, 2020 at 21:52, ~rexfuzzle wrote:

Sorry, I meant webassembly, not web pack- I corrected the post. I'll work on the smallest possible example and post it here when I've got one that errors every time.

I realise that this is a bad idea, but what is weird is that it works in some parts of the code for web assembly, but not others, i.e. if the http call is in the Event loop of one of the pages of the scatter example it seems to work, so that would tell me the http client is implemented. I've also tried with simple fmt.Println instead of the log which also didn't work. Anyway, here is the example: https://gist.github.com/grantstephens/da5f7f947a4edaec725c6c88fedf8f30

This gives me an error that looks like: ```` fatal error: all goroutines are asleep - deadlock! wasmexec.js:47:14 wasmexec.js:47:14 goroutine 1 [chan receive]: wasm_exec.js:47:14

gioui.org/app/internal/window.Main(...) ````

Can you provide the full stack trace from the deadlock crash? Further, what's your Go version (go version)? Another similar issue came to mind:

https://github.com/golang/go/issues/35256

but I suspect your issue is caused by a fundamental webassembly restriction as noted in 34478:

https://github.com/golang/go/issues/34478#issuecomment-534290562

That is, blocking operations (such as a HTTP GET) won't work from callbacks. That would explain why your GET works from some parts of your code.

~rexfuzzle 4 months ago

Ah, ok, suspected something like that. Thank you for your help. My stack trace is:

fatal error: all goroutines are asleep - deadlock! wasm_exec.js:47:14
<empty string> wasm_exec.js:47:14
goroutine 1 [chan receive]: wasm_exec.js:47:14
gioui.org/app/internal/window.Main(...) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/internal/window/os_js.go:398 wasm_exec.js:47:14
gioui.org/app.Main(...) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/app.go:45 wasm_exec.js:47:14
main.main() wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/src/github.com/grantstephens/webpackfail/main.go:34 +0x7 wasm_exec.js:47:14
<empty string> wasm_exec.js:47:14
goroutine 6 [select]: wasm_exec.js:47:14
net/http.(*Transport).RoundTrip(0x5dfc80, 0x89e200, 0x0, 0x0, 0x0) wasm_exec.js:47:14
    /home/grantstephens/.goenv/versions/1.14beta1/src/net/http/roundtrip_js.go:169 +0x4f wasm_exec.js:47:14
net/http.send(0x89e200, 0x110420, 0x5dfc80, 0x0, 0x0, 0x0, 0x0, 0x80c0a0, 0x825440, 0x1) wasm_exec.js:47:14
    /home/grantstephens/.goenv/versions/1.14beta1/src/net/http/client.go:252 +0x5c wasm_exec.js:47:14
net/http.(*Client).send(0x8253e0, 0x89e200, 0x0, 0x0, 0x0, 0x80c0a0, 0x0, 0x1, 0x89e200) wasm_exec.js:47:14
    /home/grantstephens/.goenv/versions/1.14beta1/src/net/http/client.go:176 +0x13 wasm_exec.js:47:14
net/http.(*Client).do(0x8253e0, 0x89e200, 0x0, 0x0, 0x0) wasm_exec.js:47:14
    /home/grantstephens/.goenv/versions/1.14beta1/src/net/http/client.go:692 +0x38 wasm_exec.js:47:14
net/http.(*Client).Do(...) wasm_exec.js:47:14
    /home/grantstephens/.goenv/versions/1.14beta1/src/net/http/client.go:560 wasm_exec.js:47:14
net/http.(*Client).Get(0x8253e0, 0xb5baa, 0x1c, 0x58, 0x884e0, 0x6042e0) wasm_exec.js:47:14
    /home/grantstephens/.goenv/versions/1.14beta1/src/net/http/client.go:449 +0xe wasm_exec.js:47:14
main.kitchen(0x828420, 0x82a140) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/src/github.com/grantstephens/webpackfail/main.go:62 +0x3 wasm_exec.js:47:14
main.loop(0x896000, 0x0, 0x0) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/src/github.com/grantstephens/webpackfail/main.go:47 +0x1b wasm_exec.js:47:14
main.main.func1() wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/src/github.com/grantstephens/webpackfail/main.go:30 +0x3 wasm_exec.js:47:14
created by main.main wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/src/github.com/grantstephens/webpackfail/main.go:28 +0x3 wasm_exec.js:47:14
<empty string> wasm_exec.js:47:14
goroutine 7 [select]: wasm_exec.js:47:14
gioui.org/app.(*Window).run(0x896000, 0x80a220) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/window.go:301 +0xd4 wasm_exec.js:47:14
created by gioui.org/app.NewWindow wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/window.go:103 +0x14 wasm_exec.js:47:14
<empty string> wasm_exec.js:47:14
goroutine 8 [chan receive]: wasm_exec.js:47:14
gioui.org/app.(*callbacks).Event(0x8961e0, 0x110a20, 0x828660) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/window.go:194 +0x9 wasm_exec.js:47:14
gioui.org/app/internal/window.(*window).draw(0x8622c0, 0x110b01) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/internal/window/os_js.go:367 +0x15 wasm_exec.js:47:14
gioui.org/app/internal/window.NewWindow.func2(0x8622c0) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/internal/window/os_js.go:61 +0xf wasm_exec.js:47:14
created by gioui.org/app/internal/window.NewWindow wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/internal/window/os_js.go:57 +0x1e wasm_exec.js:47:14
<empty string> wasm_exec.js:47:14
goroutine 9 [select]: wasm_exec.js:47:14
gioui.org/app.(*renderLoop).renderLoop.func1(0x8286c0, 0x1171c0, 0x824d80, 0x82c660) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/loop.go:79 +0xe wasm_exec.js:47:14
created by gioui.org/app.(*renderLoop).renderLoop wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/loop.go:61 +0x3 wasm_exec.js:47:14
<empty string> wasm_exec.js:47:14
goroutine 10 [chan send]: wasm_exec.js:47:14
gioui.org/app.(*callbacks).Event(0x8961e0, 0x110aa0, 0x8a2150) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/window.go:193 +0x6 wasm_exec.js:47:14
gioui.org/app/internal/window.(*window).pointerEvent(0x8622c0, 0x81b603, 0x0, 0x7ff80001000000bb, 0x81b680) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/internal/window/os_js.go:299 +0x31 wasm_exec.js:47:14
gioui.org/app/internal/window.(*window).addEventListeners.func2(0x7ff8000100000015, 0x81b670, 0x8aa730, 0x1, 0x1, 0x81b678, 0x8) wasm_exec.js:47:14
    /home/grantstephens/Sync/Code/Go/pkg/mod/gioui.org@v0.0.0-20200116122050-18cddc030077/app/internal/window/os_js.go:118 +0x3 wasm_exec.js:47:14
syscall/js.handleEvent() wasm_exec.js:47:14
    /home/grantstephens/.goenv/versions/1.14beta1/src/syscall/js/func.go:90 +0x24
Register here or Log in to comment, or comment via email.