emscripten: Add epoll support - #5427
Merged
Merged
Conversation
8 tasks
guybedford
force-pushed
the
emscripten-apis
branch
from
August 18, 2026 23:37
1d5c1a0 to
16584c2
Compare
tgross35
reviewed
Aug 19, 2026
This comment has been minimized.
This comment has been minimized.
guybedford
force-pushed
the
emscripten-apis
branch
from
August 19, 2026 16:24
16584c2 to
88bcf99
Compare
This comment has been minimized.
This comment has been minimized.
Emscripten restored the `sys/epoll.h` header in 6.0.2 and implements `epoll_create`, `epoll_create1`, `epoll_ctl`, `epoll_wait` and `epoll_pwait` in the JS filesystem as of 6.0.8. Version detection in libc-test now also tracks the tiny version component so that point releases can be distinguished, and parses the uppercase `__EMSCRIPTEN_MAJOR__` macro forms used since Emscripten 5.0.1, where the lowercase names became non-integer aliases. Link: https://github.com/emscripten-core/emscripten/blob/4483d70a78098ed5d860dff2dc21f3025b2da2ee/system/lib/libc/musl/include/sys/epoll.h#L17 Link: https://github.com/emscripten-core/emscripten/blob/4483d70a78098ed5d860dff2dc21f3025b2da2ee/system/lib/libc/musl/include/sys/epoll.h#L70-L74 Link: emscripten-core/emscripten#27206 Link: emscripten-core/emscripten#27207
guybedford
force-pushed
the
emscripten-apis
branch
from
August 19, 2026 21:32
88bcf99 to
0cf3493
Compare
Collaborator
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
tgross35
approved these changes
Aug 20, 2026
tgross35
pushed a commit
to tgross35/rust-libc
that referenced
this pull request
Sep 4, 2026
Emscripten restored the `sys/epoll.h` header in 6.0.2 and implements `epoll_create`, `epoll_create1`, `epoll_ctl`, `epoll_wait` and `epoll_pwait` in the JS filesystem as of 6.0.8. Version detection in libc-test now also tracks the tiny version component so that point releases can be distinguished, and parses the uppercase `__EMSCRIPTEN_MAJOR__` macro forms used since Emscripten 5.0.1, where the lowercase names became non-integer aliases. Link: https://github.com/emscripten-core/emscripten/blob/4483d70a78098ed5d860dff2dc21f3025b2da2ee/system/lib/libc/musl/include/sys/epoll.h#L17 Link: https://github.com/emscripten-core/emscripten/blob/4483d70a78098ed5d860dff2dc21f3025b2da2ee/system/lib/libc/musl/include/sys/epoll.h#L70-L74 Link: emscripten-core/emscripten#27206 Link: emscripten-core/emscripten#27207 (backport <rust-lang#5427>) (cherry picked from commit 04c162b)
Merged
tgross35
pushed a commit
to tgross35/rust-libc
that referenced
this pull request
Sep 4, 2026
Emscripten restored the `sys/epoll.h` header in 6.0.2 and implements `epoll_create`, `epoll_create1`, `epoll_ctl`, `epoll_wait` and `epoll_pwait` in the JS filesystem as of 6.0.8. Version detection in libc-test now also tracks the tiny version component so that point releases can be distinguished, and parses the uppercase `__EMSCRIPTEN_MAJOR__` macro forms used since Emscripten 5.0.1, where the lowercase names became non-integer aliases. Link: https://github.com/emscripten-core/emscripten/blob/4483d70a78098ed5d860dff2dc21f3025b2da2ee/system/lib/libc/musl/include/sys/epoll.h#L17 Link: https://github.com/emscripten-core/emscripten/blob/4483d70a78098ed5d860dff2dc21f3025b2da2ee/system/lib/libc/musl/include/sys/epoll.h#L70-L74 Link: emscripten-core/emscripten#27206 Link: emscripten-core/emscripten#27207 (backport <rust-lang#5427>) (cherry picked from commit 04c162b)
guybedford
added a commit
to guybedford/tokio
that referenced
this pull request
Sep 9, 2026
Follow-on to tokio-rs#8285, enabling `tokio::net` on Emscripten over mio's epoll selector and Node's raw sockets (`-sNODERAWSOCKETS`). The I/O driver is the native one. Under JSPI, Emscripten's `epoll_wait` is a blocking wait that suspends on the host event loop, resuming on readiness (or the mio waker pipe) or the deadline, so `park` and `park_timeout` need nothing target-specific. The one addition is for the scheduler's zero-duration maintenance park: a zero-timeout `epoll_wait` is a synchronous probe, and the host loop is the only producer of readiness, so the driver yields one host turn first, as the zero-duration `ParkThread` park already does. Without JSPI a real wait panics rather than spinning, matching the existing park semantics. Under pthreads with `-sPROXY_TO_PTHREAD` the wait blocks on the worker as on native, with no target-specific code at all. TcpStream/TcpListener/UdpSocket, stream `AF_UNIX` sockets, `lookup_host` and `AsyncFd` work as on native. Gated where Node lacks the primitive: datagram `AF_UNIX` (`UnixDatagram`, `UnixSocket::new_datagram`), `socketpair(2)` (`UnixStream::pair`), and `SO_PEERCRED` (`peer_cred` reports unsupported). Name resolution goes through Emscripten's synchronous `getaddrinfo`, which maps hostnames to synthetic addresses, so the `localhost` tests are ignored on this target. CI adds `net` to both emscripten test runs on the released emsdk: JSPI (815 passed, 0 failed, 19 ignored) and pthreads, which regains `-sPROXY_TO_PTHREAD` (818 passed, 0 failed, 19 ignored). The JSPI run uses Rust beta until 1.99 is stable, which is where `OwnedFd::try_clone` (mio's registry handle) gains Emscripten support. TEMPORARY: `mio` comes from tokio-rs/mio#1969 until released, which in turn takes `libc` from the `libc-0.2` branch for its emscripten epoll bindings (rust-lang/libc#5427).
guybedford
added a commit
to guybedford/tokio
that referenced
this pull request
Sep 11, 2026
Follow-on to tokio-rs#8285, enabling `tokio::net` on Emscripten over mio's epoll selector and Node's raw sockets (`-sNODERAWSOCKETS`). The I/O driver is the native one. Under JSPI, Emscripten's `epoll_wait` is a blocking wait that suspends on the host event loop, resuming on readiness (or the mio waker pipe) or the deadline, so `park` and `park_timeout` need nothing target-specific beyond `jspi::io_wait`, which makes the wait a park in the JSPI sense: it leaves the runtime around the `epoll_wait` as the timer park does, so sibling activations may drive their own runtime while it is suspended. It also handles the scheduler's zero-duration maintenance park: a zero-timeout `epoll_wait` is a synchronous probe, and the host loop is the only producer of readiness, so the driver yields one host turn first, as the zero-duration `ParkThread` park already does. Without JSPI a real wait panics rather than spinning, matching the existing park semantics. Under pthreads with `-sPROXY_TO_PTHREAD` the wait blocks on the worker as on native, with no target-specific code at all. A wait with no deadline is a real `epoll_wait` that a socket could wake, so it suspends rather than panicking as the reactor-less park does; the `rt_emscripten_block_on` test of that panic is gated off `net`. TcpStream/TcpListener/UdpSocket, stream `AF_UNIX` sockets, `lookup_host` and `AsyncFd` work as on native. Gated where Node lacks the primitive: datagram `AF_UNIX` (`UnixDatagram`, `UnixSocket::new_datagram`), `socketpair(2)` (`UnixStream::pair`), and `SO_PEERCRED` (`peer_cred` reports unsupported). Name resolution goes through Emscripten's synchronous `getaddrinfo`, which maps hostnames to synthetic addresses, so the `localhost` tests are ignored on this target. CI adds `net` to both emscripten test runs on the released emsdk: JSPI (846 passed, 0 failed, 19 ignored) and pthreads, which regains `-sPROXY_TO_PTHREAD` (818 passed, 0 failed, 19 ignored). The JSPI lane links a `--pre-js` that fails a test binary whose `main` never returns: a park that suspends with no wake source leaves Node's event loop to drain and the process to exit 0, which cargo would otherwise take as success. The JSPI run uses Rust beta until 1.99 is stable, which is where `OwnedFd::try_clone` (mio's registry handle) gains Emscripten support. TEMPORARY: `mio` comes from tokio-rs/mio#1969 until released, which in turn takes `libc` from the `libc-0.2` branch for its emscripten epoll bindings (rust-lang/libc#5427).
guybedford
added a commit
to guybedford/tokio
that referenced
this pull request
Sep 11, 2026
Follow-on to tokio-rs#8285, enabling `tokio::net` on Emscripten over mio's epoll selector and Node's raw sockets (`-sNODERAWSOCKETS`). The I/O driver is the native one. Under JSPI, Emscripten's `epoll_wait` is a blocking wait that suspends on the host event loop, resuming on readiness (or the mio waker pipe) or the deadline, so `park` and `park_timeout` need nothing target-specific beyond `jspi::io_wait`, which makes the wait a park in the JSPI sense: it leaves the runtime around the `epoll_wait` as the timer park does, so sibling activations may drive their own runtime while it is suspended. It also handles the scheduler's zero-duration maintenance park: a zero-timeout `epoll_wait` is a synchronous probe, and the host loop is the only producer of readiness, so the driver yields one host turn first, as the zero-duration `ParkThread` park already does. Without JSPI a real wait panics rather than spinning, matching the existing park semantics. Under pthreads with `-sPROXY_TO_PTHREAD` the wait blocks on the worker as on native, with no target-specific code at all. A wait with no deadline is a real `epoll_wait` that a socket could wake, so it suspends rather than panicking as the reactor-less park does; the `rt_emscripten_block_on` test of that panic is gated off `net`. TcpStream/TcpListener/UdpSocket, stream `AF_UNIX` sockets, `lookup_host` and `AsyncFd` work as on native. Gated where Node lacks the primitive: datagram `AF_UNIX` (`UnixDatagram`, `UnixSocket::new_datagram`), `socketpair(2)` (`UnixStream::pair`), and `SO_PEERCRED` (`peer_cred` reports unsupported). Name resolution goes through Emscripten's synchronous `getaddrinfo`, which maps hostnames to synthetic addresses, so the `localhost` tests are ignored on this target. CI adds `net` to both emscripten test runs on the released emsdk: JSPI (846 passed, 0 failed, 19 ignored) and pthreads, which regains `-sPROXY_TO_PTHREAD` (818 passed, 0 failed, 19 ignored). The JSPI lane links a `--pre-js` that fails a test binary whose `main` never returns: a park that suspends with no wake source leaves Node's event loop to drain and the process to exit 0, which cargo would otherwise take as success. The JSPI run uses Rust beta until 1.99 is stable, which is where `OwnedFd::try_clone` (mio's registry handle) gains Emscripten support. TEMPORARY: `mio` comes from tokio-rs/mio#1969 until released, which in turn takes `libc` from the `libc-0.2` branch for its emscripten epoll bindings (rust-lang/libc#5427).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This adds the epoll APIs for the
wasm32-unknown-emscriptentarget. Emscripten restored thesys/epoll.hheader in 6.0.2 (emscripten-core/emscripten#27206) and implements the epoll functions in the JS filesystem as of the upcoming 6.0.8 (emscripten-core/emscripten#27207).EPOLL_CLOEXECandepoll_create,epoll_create1,epoll_ctl,epoll_waitandepoll_pwaitfor Emscripten (theepoll_eventtype andEPOLL*constants were already defined for the target)test_emscripten, version-gated so that all currently released Emscripten versions (including the 3.1.68 CI pin) are unaffected__EMSCRIPTEN_major__macros are non-integer aliases of new uppercase forms, and the tiny version component is now tracked so that point releases can be distinguishedTested against Emscripten stable 6.0.7, where the header, type and constant tests run and pass, with the function link tests remaining version-gated until 6.0.8, and against the fully gated skip path.