Commit Graph
11 Commits
Author SHA1 Message Date
Karl Seguin 47eb1b8581 make acquireArena names more consistent with each other 2026-09-14 07:44:21 +08:00
Scott Taylor c284fce11a cdp: preserve message storage across reentrant notifications
Runtime.consoleAPICalled serialized object arguments with JSON.stringify,
which can run getters and toJSON callbacks. A callback can log again or
navigate, emitting further CDP events while the outer event is being built.
Resetting send_arena after each send and notification_arena after each
handler then invalidates the outer message's buffers. This produces
use-after-free in debug builds or malformed JSON that disconnects clients.

Scope both arenas to the outermost send or notification handler, including
inspector messages and error paths. Also match Chrome's console argument
representation: objects remain remote handles, primitives carry value,
and non-JSON numbers and bigints use unserializableValue. Console logging
must not invoke object getters or toJSON as a serialization side effect.

Test complete nested WebSocket messages, failure recovery, nested legacy
Console notifications, and primitive/object protocol shapes.
2026-09-13 19:27:18 -04:00
Karl Seguin bcf69ced9c address feedback
tighten socket ownership (on error paths)

allow reaper to be disabled

Handle window where link is being destroyed, worker is still alive, and client
attempts to re-link.
2026-09-11 05:11:36 +08:00
Karl Seguin 8ad9eaf48d webdriver: HTTP WebDriver session management
This is a small step towards WebDriver supports (non-bidi). It allows creating
and deleting a BiDi "Session" (e.g. a worker). It also allows attaching a BiDi
driver to an HTTP-created BiDi session (the typical selenium startup flow).

This change unblocks the most basic setup/teardown of Selenium, so it still
isn't enough to actually use a Selenium script as-is. But it's significant
because it models a worker (thread) that isn't tied to a WebSocket, something we
haven't had before.

A consequence of a pure HTTP Session is that we don't have a clear cleanup
signal. There is no "the socket is disconnected". There's a new HTTP reaper
which kills HTTP Sessions after --http-session-timeout. It's expected that
drivers properly DELETE /session/:id. I imagine we're going to run into
--cdp-max-connections limits and need to tweak this code. BUT, this entire flow
is only enabled with --protocol webdriver, so it won't impact exiting CDP users.
2026-09-11 05:11:26 +08:00
Karl Seguin b21ec60853 Merge pull request #3411 from lightpanda-io/remove-unused-imports
chore: remove unused imports
2026-09-07 07:20:50 +08:00
Navid EMAD ae6a646797 link test: check the O_NONBLOCK bit, not the whole F_GETFL word
macOS adds an internal 'was written' bit to F_GETFL once the fd has been
written to, so the exact comparison fails there (expected 6, found 65542)
even though the send timed out as intended and O_NONBLOCK is still set.
2026-09-06 20:06:27 +08:00
Karl Seguin faad885913 improve macos test stability 2026-09-06 18:13:08 +08:00
Karl Seguin a5e27869d3 chore: remove unused imports 2026-09-05 17:51:47 +08:00
Karl Seguin 7f29bf6931 500 on write error and remove blocking writes 2026-09-03 06:47:53 +08:00
Karl Seguin 17c2aa7d1f Hardening
Give it one pass through some Claude fuzz testing. Add a max message size,
protect against weird interactions during a shutdown and we had some pending
accepts. Put a time limit on blocked writes.
2026-09-03 06:47:53 +08:00
Karl Seguin e6241c1918 serve: Improve cdp/bidi server
Significant rework of the CDP/BiDi server. There are two main changes:

1 - poll replaced with EPoll/Kqueue (1)
2 - make http serving a first class citizen

The change from poll -> epoll/kqueue isn't performance driven, it's just about
tighter code. Both epoll and kqueue let you associate arbitrary data with a
socket, so we don't need to keep arrays in sync in order to associate a socket
with a CDP by index. They both provide some event/notification mechanism, which
is cleaner than the pipe required by poll.

The poll -> epoll/kqueue change could almost have been mechanical. Making HTTP
a first class citizen is the more significant of the two changes

In `main`, a new connection always spawns a thread and, until does its own
little read loop until the connection is upgraded. This is not efficient, it
uses up a connection slot, and it's inconsistent with the final WebSocket
connection which _is_ polled off the main loop. Using up a slot means that
keepalive isn't possible, else HTTP connections would quickly use up all
available slots/threads.

This commit parses and serves HTTP requests on the main thread (safe
because none of the processing is blocking). The approach is better streamlined
for HTTP requests which never upgrade (/metrics, WebDriver) without causing
any performance overhead for those that do. It simplifies some things (e.g. an
"http" socket or a "websocket" socket is monitored and read in a similar manner
(on the main loop)). It makes other things more complicated; the flow is no
longer accept -> spawn -> upgrade -> websocket loop. It's loop -> accept -> loop
-> process -> (http | ws).

This is built ontop of the BiDi branch because (a) WebDriver is what needs
better  HTTP support and (b) some of the more mechanical changes already exist
in that branch (e.g. src/cdp/, src/server.zig -> src/server/*)

(1) kqueue landing in 2 commits from now on this branch.
2026-09-03 06:47:49 +08:00