Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions src/lib/libwasi.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,18 @@ var WasiLibrary = {
var ptr = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_base, '*') }}};
var len = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_len, '*') }}};
iov += {{{ C_STRUCTS.iovec.__size__ }}};
var curr = FS.read(stream, HEAP8, ptr, len, offset);
try {
var curr = FS.read(stream, HEAP8, ptr, len, offset);
} catch (e) {
// On a non-blocking stream a subsequent read may would-block after we
// already gathered data. POSIX readv is a single gather-read: return
// what we have rather than failing the whole call.
if (ret > 0 && e instanceof FS.ErrnoError &&
(e.errno == {{{ cDefs.EAGAIN }}} || e.errno == {{{ cDefs.EWOULDBLOCK }}})) {
break;
}
throw e;
}
if (curr < 0) return -1;
ret += curr;
if (curr < len) break; // nothing more to read
Expand All @@ -219,7 +230,18 @@ var WasiLibrary = {
var ptr = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_base, '*') }}};
var len = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_len, '*') }}};
iov += {{{ C_STRUCTS.iovec.__size__ }}};
var curr = FS.write(stream, HEAP8, ptr, len, offset);
try {
var curr = FS.write(stream, HEAP8, ptr, len, offset);
} catch (e) {
// On a non-blocking stream a subsequent write may would-block after we
// already sent data. POSIX writev is a single gather-write: return
// what we have rather than failing the whole call.
if (ret > 0 && e instanceof FS.ErrnoError &&
(e.errno == {{{ cDefs.EAGAIN }}} || e.errno == {{{ cDefs.EWOULDBLOCK }}})) {
break;
}
throw e;
}
if (curr < 0) return -1;
ret += curr;
if (curr < len) {
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_ctors1.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 19183,
"a.out.js.gz": 7971,
"a.out.js": 19321,
"a.out.js.gz": 8000,
"a.out.nodebug.wasm": 132556,
"a.out.nodebug.wasm.gz": 49942,
"total": 151739,
"total_gz": 57913,
"total": 151877,
"total_gz": 57942,
"sent": [
"__cxa_throw",
"_abort_js",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_ctors2.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 19160,
"a.out.js.gz": 7957,
"a.out.js": 19298,
"a.out.js.gz": 7986,
"a.out.nodebug.wasm": 131982,
"a.out.nodebug.wasm.gz": 49601,
"total": 151142,
"total_gz": 57558,
"total": 151280,
"total_gz": 57587,
"sent": [
"__cxa_throw",
"_abort_js",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_except.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 23158,
"a.out.js.gz": 8955,
"a.out.js": 23296,
"a.out.js.gz": 8993,
"a.out.nodebug.wasm": 172466,
"a.out.nodebug.wasm.gz": 57476,
"total": 195624,
"total_gz": 66431,
"total": 195762,
"total_gz": 66469,
"sent": [
"__cxa_begin_catch",
"__cxa_end_catch",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_except_wasm.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 18982,
"a.out.js.gz": 7888,
"a.out.js": 19120,
"a.out.js.gz": 7923,
"a.out.nodebug.wasm": 147881,
"a.out.nodebug.wasm.gz": 55369,
"total": 166863,
"total_gz": 63257,
"total": 167001,
"total_gz": 63292,
"sent": [
"_abort_js",
"_tzset_js",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_except_wasm_legacy.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 19060,
"a.out.js.gz": 7913,
"a.out.js": 19198,
"a.out.js.gz": 7948,
"a.out.nodebug.wasm": 145687,
"a.out.nodebug.wasm.gz": 54986,
"total": 164747,
"total_gz": 62899,
"total": 164885,
"total_gz": 62934,
"sent": [
"_abort_js",
"_tzset_js",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_lto.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 18526,
"a.out.js.gz": 7665,
"a.out.js": 18665,
"a.out.js.gz": 7692,
"a.out.nodebug.wasm": 102063,
"a.out.nodebug.wasm.gz": 39527,
"total": 120589,
"total_gz": 47192,
"total": 120728,
"total_gz": 47219,
"sent": [
"a (emscripten_resize_heap)",
"b (_setitimer_js)",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_mangle.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 23208,
"a.out.js.gz": 8976,
"a.out.js": 23346,
"a.out.js.gz": 9013,
"a.out.nodebug.wasm": 238895,
"a.out.nodebug.wasm.gz": 79814,
"total": 262103,
"total_gz": 88790,
"total": 262241,
"total_gz": 88827,
"sent": [
"__cxa_begin_catch",
"__cxa_end_catch",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_cxx_noexcept.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 19183,
"a.out.js.gz": 7971,
"a.out.js": 19321,
"a.out.js.gz": 8000,
"a.out.nodebug.wasm": 134556,
"a.out.nodebug.wasm.gz": 50787,
"total": 153739,
"total_gz": 58758,
"total": 153877,
"total_gz": 58787,
"sent": [
"__cxa_throw",
"_abort_js",
Expand Down
12 changes: 11 additions & 1 deletion test/codesize/test_codesize_file_preload.expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,17 @@ var onPreRuns = [];
var ptr = HEAPU32[((iov) >> 2)];
var len = HEAPU32[(((iov) + (4)) >> 2)];
iov += 8;
var curr = FS.write(stream, HEAP8, ptr, len, offset);
try {
var curr = FS.write(stream, HEAP8, ptr, len, offset);
} catch (e) {
// On a non-blocking stream a subsequent write may would-block after we
// already sent data. POSIX writev is a single gather-write: return
// what we have rather than failing the whole call.
if (ret > 0 && e instanceof FS.ErrnoError && (e.errno == 6 || e.errno == 6)) {
break;
}
throw e;
}
if (curr < 0) return -1;
ret += curr;
if (curr < len) {
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_file_preload.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 22239,
"a.out.js.gz": 9251,
"a.out.js": 22308,
"a.out.js.gz": 9277,
"a.out.nodebug.wasm": 1666,
"a.out.nodebug.wasm.gz": 945,
"total": 23905,
"total_gz": 10196,
"total": 23974,
"total_gz": 10222,
"sent": [
"a (fd_write)"
],
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_files_js_fs.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 17831,
"a.out.js.gz": 7311,
"a.out.js": 17969,
"a.out.js.gz": 7342,
"a.out.nodebug.wasm": 381,
"a.out.nodebug.wasm.gz": 258,
"total": 18212,
"total_gz": 7569,
"total": 18350,
"total_gz": 7600,
"sent": [
"a (fd_write)",
"b (fd_read)",
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_hello_dylink.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 26190,
"a.out.js.gz": 11198,
"a.out.js": 26260,
"a.out.js.gz": 11231,
"a.out.nodebug.wasm": 17861,
"a.out.nodebug.wasm.gz": 9019,
"total": 44051,
"total_gz": 20217,
"total": 44121,
"total_gz": 20250,
"sent": [
"__syscall_stat64",
"emscripten_resize_heap",
Expand Down
4 changes: 2 additions & 2 deletions test/codesize/test_codesize_hello_dylink_all.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"a.out.js": 268279,
"a.out.js": 268425,
"a.out.nodebug.wasm": 587978,
"total": 856257,
"total": 856403,
"sent": [
"IMG_Init",
"IMG_Load",
Expand Down
75 changes: 75 additions & 0 deletions test/fs/test_readv_eagain.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2024 The Emscripten Authors. All rights reserved.
* Emscripten is available under two separate licenses, the MIT license and the
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*/

// Regression test: a partial gather-read/write on a non-blocking stream must
// return the bytes already transferred rather than propagating EAGAIN from a
// later iovec.

#include <assert.h>
#include <emscripten/emscripten.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/uio.h>
#include <unistd.h>

int main() {
EM_ASM({
var eagain = $0;

// Device that satisfies the first read fully, then would-blocks.
var readCalls = 0;
var rdev = FS.makedev(64, 0);
FS.registerDevice(rdev, {
read: (stream, buffer, offset, length, pos) => {
if (++readCalls == 1) {
for (var i = 0; i < length; i++) buffer[offset + i] = 65 + i;
return length;
}
throw new FS.ErrnoError(eagain);
}
});
FS.mkdev('/rdev', rdev);

// Device that accepts the first write fully, then would-blocks.
var writeCalls = 0;
var wdev = FS.makedev(64, 1);
FS.registerDevice(wdev, {
write: (stream, buffer, offset, length, pos) => {
if (++writeCalls == 1) return length;
throw new FS.ErrnoError(eagain);
}
});
FS.mkdev('/wdev', wdev);
}, EAGAIN);

int rfd = open("/rdev", O_RDONLY);
assert(rfd >= 0);
char buf0[4] = {0};
char buf1[4] = {0};
struct iovec riov[] = {{.iov_base = buf0, .iov_len = 4},
{.iov_base = buf1, .iov_len = 4}};
ssize_t nread = readv(rfd, riov, 2);
// First iovec filled; second would-block -> partial success, not EAGAIN.
assert(nread == 4);
assert(memcmp(buf0, "ABCD", 4) == 0);
close(rfd);

int wfd = open("/wdev", O_WRONLY);
assert(wfd >= 0);
char out0[4] = "ABCD";
char out1[4] = "EFGH";
struct iovec wiov[] = {{.iov_base = out0, .iov_len = 4},
{.iov_base = out1, .iov_len = 4}};
ssize_t nwrite = writev(wfd, wiov, 2);
assert(nwrite == 4);
close(wfd);

printf("done\n");
return 0;
}
3 changes: 3 additions & 0 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -6037,6 +6037,9 @@ def test_fs_readv(self):
def test_fs_writev(self):
self.do_runf('fs/test_writev.c', 'done\n', cflags=['-sFORCE_FILESYSTEM'])

def test_fs_readv_eagain(self):
self.do_runf('fs/test_readv_eagain.c', 'done\n', cflags=['-sFORCE_FILESYSTEM'])

def test_fs_64bit(self):
if self.get_setting('WASMFS'):
self.set_setting('FORCE_FILESYSTEM')
Expand Down