From f4314a331142423f9abda9cab7464d6d3ed6c8db Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Fri, 27 Mar 2026 17:31:50 +0100 Subject: [PATCH] fix(zephyr): stdio handling Signed-off-by: Marco Casaroli --- .../platform/zephyr/platform_internal.h | 7 +- core/shared/platform/zephyr/zephyr_file.c | 86 +++++++++++++++---- core/shared/platform/zephyr/zephyr_socket.c | 6 +- 3 files changed, 80 insertions(+), 19 deletions(-) diff --git a/core/shared/platform/zephyr/platform_internal.h b/core/shared/platform/zephyr/platform_internal.h index 134b5c2b5f..d68db0dc12 100644 --- a/core/shared/platform/zephyr/platform_internal.h +++ b/core/shared/platform/zephyr/platform_internal.h @@ -260,8 +260,11 @@ typedef struct zephyr_fs_desc { // definition of zephyr_handle typedef struct zephyr_handle { - int fd; - bool is_sock; + int fd; // virtual fd number (0=stdin, 1=stdout, 2=stderr) or desc_array + // index + bool is_sock; // true if this is a socket + bool is_stdio; // true if this is a stdio handle (stdin/stdout/stderr) + int raw_fd; // real OS file descriptor for stdio, or -1 if using defaults } zephyr_handle; typedef struct zephyr_handle *os_file_handle; diff --git a/core/shared/platform/zephyr/zephyr_file.c b/core/shared/platform/zephyr/zephyr_file.c index 1f48bc010c..d66a0f8ed4 100644 --- a/core/shared/platform/zephyr/zephyr_file.c +++ b/core/shared/platform/zephyr/zephyr_file.c @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -369,6 +370,8 @@ os_open_preopendir(const char *path, os_file_handle *out) (*out)->fd = index; (*out)->is_sock = false; + (*out)->is_stdio = false; + (*out)->raw_fd = -1; strncpy(prestat_dir, path, MAX_FILE_NAME + 1); prestat_dir[MAX_FILE_NAME] = '\0'; @@ -483,6 +486,8 @@ os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, (*out)->fd = index; (*out)->is_sock = false; + (*out)->is_stdio = false; + (*out)->raw_fd = -1; return __WASI_ESUCCESS; } @@ -540,8 +545,12 @@ os_close(os_file_handle handle, bool is_stdio) int rc; struct zephyr_fs_desc *ptr = NULL; - if (is_stdio) + if (is_stdio) { + /* Don't close the underlying fd - the caller owns it. + * Just free the handle struct. */ + BH_FREE(handle); return __WASI_ESUCCESS; + } if (handle->is_sock) { rc = zsock_close(handle->fd); @@ -566,7 +575,8 @@ __wasi_errno_t os_preadv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, __wasi_filesize_t offset, size_t *nread) { - if (handle->fd == STDIN_FILENO) { + /* Positional read is not supported on stdio handles */ + if (handle->is_stdio) { return __WASI_ENOSYS; } @@ -606,6 +616,11 @@ __wasi_errno_t os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, __wasi_filesize_t offset, size_t *nwritten) { + /* Positional write is not supported on stdio handles */ + if (handle->is_stdio) { + return __WASI_ENOSYS; + } + struct zephyr_fs_desc *ptr = NULL; ssize_t total_written = 0; @@ -642,9 +657,29 @@ __wasi_errno_t os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, size_t *nread) { - struct zephyr_fs_desc *ptr = NULL; ssize_t total_read = 0; + /* Handle stdio (stdin/stdout/stderr) */ + if (handle->is_stdio) { + if (handle->raw_fd >= 0) { + /* Use the real OS file descriptor */ + for (int i = 0; i < iovcnt; i++) { + ssize_t bytes_read = + read(handle->raw_fd, iov[i].buf, iov[i].buf_len); + if (bytes_read < 0) + return convert_errno(errno); + total_read += bytes_read; + if ((size_t)bytes_read < iov[i].buf_len) + break; + } + } + /* else: no real fd, return 0 bytes (EOF) */ + *nread = total_read; + return __WASI_ESUCCESS; + } + + struct zephyr_fs_desc *ptr = NULL; + GET_FILE_SYSTEM_DESCRIPTOR(handle->fd, ptr); // Read data into each buffer @@ -668,21 +703,34 @@ os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, return __WASI_ESUCCESS; } -/* With wasi-libc we need to redirect write on stdout/err to printf */ -// TODO: handle write on stdin __wasi_errno_t os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, size_t *nwritten) { ssize_t total_written = 0; - if (os_is_virtual_fd(handle->fd)) { - FILE *fd = (handle->fd == STDERR_FILENO) ? stderr : stdout; - for (int i = 0; i < iovcnt; i++) { - ssize_t bytes_written = fwrite(iov[i].buf, 1, iov[i].buf_len, fd); - if (bytes_written < 0) - return convert_errno(-bytes_written); - total_written += bytes_written; + /* Handle stdio (stdin/stdout/stderr) */ + if (handle->is_stdio) { + if (handle->raw_fd >= 0) { + /* Use the real OS file descriptor */ + for (int i = 0; i < iovcnt; i++) { + ssize_t bytes_written = + write(handle->raw_fd, iov[i].buf, iov[i].buf_len); + if (bytes_written < 0) + return convert_errno(errno); + total_written += bytes_written; + } + } + else { + /* No real fd: fall back to fwrite on stdout/stderr */ + FILE *f = (handle->fd == STDERR_FILENO) ? stderr : stdout; + for (int i = 0; i < iovcnt; i++) { + ssize_t bytes_written = + fwrite(iov[i].buf, 1, iov[i].buf_len, f); + if (bytes_written < 0) + return convert_errno(-bytes_written); + total_written += bytes_written; + } } *nwritten = total_written; @@ -963,6 +1011,8 @@ os_convert_stdin_handle(os_raw_file_handle raw_stdin) handle->fd = STDIN_FILENO; handle->is_sock = false; + handle->is_stdio = true; + handle->raw_fd = raw_stdin >= 0 ? raw_stdin : -1; return handle; } @@ -975,6 +1025,8 @@ os_convert_stdout_handle(os_raw_file_handle raw_stdout) handle->fd = STDOUT_FILENO; handle->is_sock = false; + handle->is_stdio = true; + handle->raw_fd = raw_stdout >= 0 ? raw_stdout : -1; return handle; } @@ -987,6 +1039,8 @@ os_convert_stderr_handle(os_raw_file_handle raw_stderr) handle->fd = STDERR_FILENO; handle->is_sock = false; + handle->is_stdio = true; + handle->raw_fd = raw_stderr >= 0 ? raw_stderr : -1; return handle; } @@ -1182,17 +1236,17 @@ os_compare_file_handle(os_file_handle handle1, os_file_handle handle2) bool os_is_stdin_handle(os_file_handle handle) { - return (handle == (os_file_handle)stdin); + return handle != NULL && handle->is_stdio && handle->fd == STDIN_FILENO; } bool os_is_stdout_handle(os_file_handle handle) { - return (handle == (os_file_handle)stdout); + return handle != NULL && handle->is_stdio && handle->fd == STDOUT_FILENO; } bool os_is_stderr_handle(os_file_handle handle) { - return (handle == (os_file_handle)stderr); -} \ No newline at end of file + return handle != NULL && handle->is_stdio && handle->fd == STDERR_FILENO; +} diff --git a/core/shared/platform/zephyr/zephyr_socket.c b/core/shared/platform/zephyr/zephyr_socket.c index 6d108623e3..1deed7c49f 100644 --- a/core/shared/platform/zephyr/zephyr_socket.c +++ b/core/shared/platform/zephyr/zephyr_socket.c @@ -203,6 +203,8 @@ os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) } (*sock)->is_sock = true; + (*sock)->is_stdio = false; + (*sock)->raw_fd = -1; if ((*sock)->fd == -1) { BH_FREE(*sock); @@ -289,6 +291,8 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, } (*sock)->is_sock = true; + (*sock)->is_stdio = false; + (*sock)->raw_fd = -1; return BHT_OK; } @@ -1059,4 +1063,4 @@ int os_poll(os_poll_file_handle *fds, os_nfds_t nfs, int timeout) { return zsock_poll(fds, nfs, timeout); -} \ No newline at end of file +}