aboutsummaryrefslogtreecommitdiff
path: root/src/syscall
diff options
context:
space:
mode:
authorRichard Musiol <mail@richard-musiol.de>2019-04-30 19:16:23 +0200
committerBrad Fitzpatrick <bradfitz@golang.org>2019-04-30 22:41:20 +0000
commit6505b4853196a172cfe4dd161072dfb8afb6b0be (patch)
tree01aab7e4e269aedac53ef9b20b3dc1e4068d9868 /src/syscall
parent65b89c3542fb3d36632e404f672b41f111b8b60a (diff)
downloadgo-6505b4853196a172cfe4dd161072dfb8afb6b0be.tar.xz
syscall: on wasm, do not use typed array asynchronously
The underlying buffer of a typed array becomes invalid as soon as we grow the WebAssembly memory, which can happen at any time while Go code runs. This is a known limitation, see https://golang.org/cl/155778. As a consequence, using a typed array with one of the asynchronous read/write operations of Node.js' fs module is dangerous, since it may become invalid while the asynchronous operation has not finished yet. The result of this situation is most likely undefined. I am not aware of any nice solution to this issue, so this change adds a workaround of using an additional typed array which is not backed by WebAssembly memory and copying the bytes between the two typed arrays. Maybe WebAssembly will come up with a better solution in the future. Fixes #31702. Change-Id: Iafc2a0fa03c81db414520bd45a1a17c00080b61e Reviewed-on: https://go-review.googlesource.com/c/go/+/174304 Run-TryBot: Richard Musiol <neelance@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src/syscall')
-rw-r--r--src/syscall/fs_js.go31
1 files changed, 23 insertions, 8 deletions
diff --git a/src/syscall/fs_js.go b/src/syscall/fs_js.go
index 89459979af..3c2dac3579 100644
--- a/src/syscall/fs_js.go
+++ b/src/syscall/fs_js.go
@@ -19,6 +19,7 @@ func now() (sec int64, nsec int32)
var jsProcess = js.Global().Get("process")
var jsFS = js.Global().Get("fs")
var constants = jsFS.Get("constants")
+var uint8Array = js.Global().Get("Uint8Array")
var (
nodeWRONLY = constants.Get("O_WRONLY").Int()
@@ -378,12 +379,16 @@ func Read(fd int, b []byte) (int, error) {
return n, err
}
- a := js.TypedArrayOf(b)
- n, err := fsCall("read", fd, a, 0, len(b), nil)
- a.Release()
+ buf := uint8Array.New(len(b))
+ n, err := fsCall("read", fd, buf, 0, len(b), nil)
if err != nil {
return 0, err
}
+
+ a := js.TypedArrayOf(b)
+ a.Call("set", buf)
+ a.Release()
+
n2 := n.Int()
f.pos += int64(n2)
return n2, err
@@ -402,8 +407,11 @@ func Write(fd int, b []byte) (int, error) {
}
a := js.TypedArrayOf(b)
- n, err := fsCall("write", fd, a, 0, len(b), nil)
+ buf := uint8Array.New(len(b))
+ buf.Call("set", a)
a.Release()
+
+ n, err := fsCall("write", fd, buf, 0, len(b), nil)
if err != nil {
return 0, err
}
@@ -413,19 +421,26 @@ func Write(fd int, b []byte) (int, error) {
}
func Pread(fd int, b []byte, offset int64) (int, error) {
- a := js.TypedArrayOf(b)
- n, err := fsCall("read", fd, a, 0, len(b), offset)
- a.Release()
+ buf := uint8Array.New(len(b))
+ n, err := fsCall("read", fd, buf, 0, len(b), offset)
if err != nil {
return 0, err
}
+
+ a := js.TypedArrayOf(b)
+ a.Call("set", buf)
+ a.Release()
+
return n.Int(), nil
}
func Pwrite(fd int, b []byte, offset int64) (int, error) {
a := js.TypedArrayOf(b)
- n, err := fsCall("write", fd, a, 0, len(b), offset)
+ buf := uint8Array.New(len(b))
+ buf.Call("set", a)
a.Release()
+
+ n, err := fsCall("write", fd, buf, 0, len(b), offset)
if err != nil {
return 0, err
}