Skip to content

[WASM_WORKERS] Fix UB in pthread_mutex with debug+hybrid builds in pthread_mutex_unlock.c - #1

Merged
stephenduong1004 merged 3 commits into
mainfrom
stephenduong1004-patch-1
Apr 16, 2026
Merged

stephenduong1004 merged 3 commits into
mainfrom
stephenduong1004-patch-1

Conversation

@stephenduong1004

Copy link
Copy Markdown
Owner

Followup of emscripten-core#26673

@stephenduong1004
stephenduong1004 merged commit e4f586d into main Apr 16, 2026
3 checks passed
stephenduong1004 pushed a commit that referenced this pull request Jul 10, 2026
…ore#27284)

$doReadv reads iovec-by-iovec via `FS.read`. On a non-blocking socket,
`FS.read` (nodeSockOps.recvmsg) throws EAGAIN when the queue is empty,
unlike a regular file which returns 0. If an earlier iovec already
consumed data and filled exactly to its length (so the `if (curr < len)
break` doesn't fire), the loop advances to the next iovec, whose
`FS.read` throws EAGAIN. The exception escaped `doReadv`, discarding the
accumulated `ret`, so the whole `readv(2)` failed with EAGAIN even
though bytes were read.

POSIX readv/writev are single gather operations: they return the
available byte count and never fail after partial success.

Observed with an mio `TcpStream` (NODERAWSOCKETS + PROXY_TO_PTHREAD +
JSPI) where an echo returned as two TCP chunks: `read_vectored` with two
iovecs hit recvmsg on iovec #1 (12 bytes, drains recvq) then recvmsg
EMPTY on iovec #2 (next chunk not yet arrived), throwing WouldBlock for
the whole call. A single-buffer read never hits it — matching "read
works, readv fails". It is timing-sensitive: if both chunks are queued
before the read, iovec #2 succeeds.

- `doReadv` and `doWritev` now catch `EAGAIN`/`EWOULDBLOCK`
`FS.ErrnoError` from a subsequent iovec and return the accumulated count
when `ret > 0`, only rethrowing when `ret == 0` (nothing transferred
yet, so the would-block belongs to the first iovec).

Adds `test/fs/test_readv_eagain.c` (wired up as `test_fs_readv_eagain`),
which registers custom devices that satisfy the first iovec fully then
throw EAGAIN, asserting both `readv` and `writev` return the partial
count rather than failing. The test aborts without the fix and passes
with it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant