diff options
| author | Richard Musiol <mail@richard-musiol.de> | 2019-04-30 19:16:23 +0200 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@golang.org> | 2019-04-30 22:41:20 +0000 |
| commit | 6505b4853196a172cfe4dd161072dfb8afb6b0be (patch) | |
| tree | 01aab7e4e269aedac53ef9b20b3dc1e4068d9868 /src/syscall | |
| parent | 65b89c3542fb3d36632e404f672b41f111b8b60a (diff) | |
| download | go-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.go | 31 |
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 } |
