mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
![Richard Musiol](/assets/img/avatar_default.png)
This change fixes a race condition between beforeIdle waking up the innermost event handler and a timer causing a different goroutine to wake up at the exact same moment. This messes up the wasm event handling and leads to memory corruption. The solution is to make beforeIdle return the goroutine that must run next and have findrunnable pick this goroutine without considering timers again. Fixes #38093 Fixes #38574 Change-Id: Iffbe99411d25c2730953d1c8b0741fd892f8e540 Reviewed-on: https://go-review.googlesource.com/c/go/+/230178 Run-TryBot: Richard Musiol <neelance@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
50 lines
859 B
Go
50 lines
859 B
Go
// +build js
|
|
// run
|
|
|
|
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Test race condition between timers and wasm calls that led to memory corruption.
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
"syscall/js"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
ch1 := make(chan struct{})
|
|
|
|
go func() {
|
|
for {
|
|
time.Sleep(5 * time.Millisecond)
|
|
ch1 <- struct{}{}
|
|
}
|
|
}()
|
|
go func() {
|
|
for {
|
|
time.Sleep(8 * time.Millisecond)
|
|
ch1 <- struct{}{}
|
|
}
|
|
}()
|
|
go func() {
|
|
time.Sleep(2 * time.Second)
|
|
os.Exit(0)
|
|
}()
|
|
|
|
for range ch1 {
|
|
ch2 := make(chan struct{}, 1)
|
|
f := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
|
ch2 <- struct{}{}
|
|
return nil
|
|
})
|
|
defer f.Release()
|
|
fn := js.Global().Get("Function").New("cb", "cb();")
|
|
fn.Invoke(f)
|
|
<-ch2
|
|
}
|
|
}
|