blob: 9712657ee2b14c83d3db43725c0cfa6a740f8775 [file]
/*
* 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}};
// writev gathers both iovecs into a single write, so the whole 8 bytes go
// out in one call and the would-block second call never happens.
ssize_t nwrite = writev(wfd, wiov, 2);
assert(nwrite == 8);
close(wfd);
printf("done\n");
return 0;
}