-sNODERAWSOCKETS DNS resolution, with general readiness callback#27182
Open
guybedford wants to merge 3 commits into
Open
-sNODERAWSOCKETS DNS resolution, with general readiness callback#27182guybedford wants to merge 3 commits into
guybedford wants to merge 3 commits into
Conversation
5bae5d9 to
917c563
Compare
…_callback Adds emscripten_poll_with_callback(fd, events, timeout, cb): a non-blocking single-fd poll that invokes cb(fd, revents) when the fd is ready or the timeout elapses. revents is passed by value. It does not suspend the caller, so it works without ASYNCIFY/JSPI. Returns -EBADF for a bad fd and -EPERM if the descriptor type can't deliver readiness callbacks (checked before arming, even when ready); closing an fd wakes its waiters with POLLNVAL. It is meant as an integration point for async runtimes and event loops that need to await I/O readiness without a blocking call or a stack switch: e.g. waiting for a socket to become readable/writable, or for an async-completion fd, and dispatching when ready. In ASYNCIFY/JSPI builds it complements blocking poll()/select(); in plain synchronous builds it is the only way to wait on an fd without spinning a poll loop. To support it, fd readiness now uses a single wait-queue on the file node, replacing three separate mechanisms (the socket event callbacks, the pipe readable handlers, and the blocking-poll notifier): - stream_ops.poll(stream) is now pure derivation; it no longer registers. - producers wake waiters via $notifyPollCallback(node, flags): SOCKFS.emit bridges socket events, PIPEFS writes wake the read end. - consumers register via $addPollCallback(node, cb): the async __syscall_poll registers one waiter per fd (re-deriving the set on wake), and emscripten_poll_with_callback registers a single-fd waiter. Sockets now feed the same seam, so blocking poll()/select() on a socket is woken by incoming data; previously sock_ops.poll() ignored the notifier. Tests: test_poll_callback (callback readiness, -EPERM/-EBADF gate, POLLNVAL close), test_poll_socket_blocking (blocking poll() woken by a delayed send; hangs before this change, passes after), and the core poll/ppoll/select/pipe blocking suites, including PROXY_TO_PTHREAD variants.
Under -sNODERAWSOCKETS, getaddrinfo() previously fabricated fake addresses via DNS.lookup_name. This adds real resolution backed by node:dns, plus an async getaddrinfo so names can be resolved without blocking. getaddrinfo() now resolves numeric addresses and /etc/hosts entries (read fresh through emscripten's FS) synchronously, and returns a full addrinfo list (one node per address). For a real hostname: - without JSPI it returns EAI_AGAIN (no synchronous DNS); resolve it via the async API below. - under JSPI it suspends the wasm stack on the node:dns lookup and returns the addresses directly (gated on ASYNCIFY == 2). The async API (available in all builds): - emscripten_dns_lookup_async(node, service, hint) takes the same inputs as getaddrinfo() and returns a pollable fd that becomes readable when resolution completes. - emscripten_dns_lookup_result(fd, struct addrinfo **res) reads the outcome: 0 on success (writing the addrinfo list to *res, freed with freeaddrinfo), or an EAI_* code on failure. The completion fd is a plain pollable descriptor: wait on it with poll/select, or without blocking via emscripten_poll_with_callback. It is a regular client of that readiness wait-queue - DNS completion does not special-case the socket message callback. freeaddrinfo now frees the whole ai_next chain; EAI_AGAIN is added to the generated struct info. Tested with test_dns_async, test_dns_callback (completion via emscripten_poll_with_callback), test_dns_async_net, test_dns_async_default, and test_dns_jspi, including PROXY_TO_PTHREAD variants.
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.
Alternative to #27162, based to #27181 for async readiness. Implementation diff is in 0019242.
This adds real DNS resolution under
-sNODERAWSOCKETSvianode:dns, along with an async syscall variant ofgetaddrinfofor non-JSPI environments.getaddrinfo()resolves numeric addresses and/etc/hostsentries (read fresh through emscripten's FS) synchronously, and returns a fulladdrinfolist. For a real hostname: without JSPI it returnsEAI_AGAIN(resolve via the async API); under JSPI it suspends the wasm stack on thenode:dnslookup and returns the addresses directly.Async API (available in all builds):
emscripten_dns_lookup_async(node, service, hint)— same inputs asgetaddrinfo(), returns a pollable fd that becomes readable when resolution completes.emscripten_dns_lookup_result(fd, struct addrinfo **res)— reads the outcome:0on success (writing theaddrinfolist to*res, freed withfreeaddrinfo), or anEAI_*code.Differences with #27162: That PR allowed the async callback for DNS lookup to be registered via
emscripten_set_socket_message_callback. Instead of "hijacking" that mechanism, this attempts to build on a more general file descriptor readiness callback mechanism provided in #27181. This could take many shapes, so happy to iterate on this further based on feedback. The core concept is that generic callback readiness avoids needing new callback listeners defined for future APIs like this in future. On readiness, the actualemscripten_dns_lookup_result()just gets called again.freeaddrinfonow frees the wholeai_nextchain;EAI_AGAINis added to the generated struct info.Tested with
test_dns_async,test_dns_callback(completion viaemscripten_poll_with_callback),test_dns_async_net,test_dns_async_default, andtest_dns_jspi, includingPROXY_TO_PTHREADvariants.