Skip to content

Linux: /evaluate that WRITES document.cookie times out (reads work) — WebKitGTK #7

Description

@slabbdev

Found while building the session-isolation CI probe (ceef773) and reproduced independently — on WebKitGTK, any /evaluate whose script writes document.cookie hangs to its 20 s timeout, while read-only evaluates on the same session return in milliseconds. Deterministic across environments:

  • docker (arm64, WebKitGTK 2.4x, navette v1.8.0): document.cookie="navette_iso=42; path=/"; document.cookie → evaluate timeout (3/3 attempts, two sessions); JSON.stringify(1+1), location.hostname, document.cookie reads → instant.
  • CI (ubuntu-24.04 x86_64): the JS-based isolation probe failed with the same signature — ~5 s navigate + 20 s evaluate-timeout = the 25 s failure seen in runs on 77118bf.

Repro

NAVETTE=http://127.0.0.1:8765
curl -X POST $NAVETTE/navigate -d '{"session":"a","url":"https://example.com"}' ...
curl -X POST $NAVETTE/evaluate -d '{"session":"a","js":"document.cookie=\"x=1\"; document.cookie"}'
# -> {"ok":false,"error":"evaluate timeout"}   after 20 s
curl -X POST $NAVETTE/evaluate -d '{"session":"a","js":"1+1"}'
# -> instant

What it is NOT

  • Not Xvfb instability (reproduced with the daemon healthy between reads).
  • Not the eval transport generally (the ipc-shim path works for every non-cookie-writing script).
  • Not cookie-value reading (reads return the jar fine).

Suspects

eval_js wraps the expression and POSTs the result through the ipc shim (window.ipc.postMessage). The hang means the script itself never reaches the postMessage — i.e. the document.cookie = … assignment blocks inside WebKitGTK on this path. Possibly an interaction between the synchronous cookie-manager write in the web process and the ipc/script context (both WKGTK quirks we've met before: the NSNumber description stringification, the with_callback-returns-empty transport).

Workarounds in place

The CI isolation probe uses state_import/state_export (backend cookie APIs) instead of page JS — immune to this. Agents on Linux hitting it can use /sessions/load for cookie writes too.

Worth checking whether a setTimeout(...,0) split (assign, then postMessage in a task) unblocks it — that would also pin down whether the assignment itself or the same-task postMessage is the blocking part.

Activity

  1. slabbdev commented on Oct 8, 2026

    @slabbdev
    OwnerAuthor

    Refined: NOT deterministic — it reproduces under contention, not on a healthy daemon

    Follow-up discrimination on a fresh container (v1.8.1, same WebKitGTK stack), all instant:

    • control plain eval → ok
    • cookie write only, no read ((function(){document.cookie="c=1"; return "written"})()) → ok — the assignment itself never blocks
    • write then read in the same task (the original "failing pattern") → ok — c=1; d=1 returned fine
    • first evaluate on a freshly-navigated session = cookie write → ok

    So the original characterization ("every cookie-WRITE evaluate times out") was wrong — it was measured on a container whose Xvfb was actively dying (it crashed with cannot open display minutes later), plus one CI run on a contended runner. The refined picture:

    A document.cookie write stalls past the 20 s evaluate timeout when the web-process/event-loop is under heavy contention (software rendering on a dying/slow X server, or a saturated CI disk — the write path flushes the cookie jar synchronously). Plain evaluates never touch disk and stay fast in the same conditions — which is why the pattern looked content-dependent.

    Candidate mitigations, in order of preference:

    1. Make the eval timeout configurable (NAVETTE_EVAL_TIMEOUT_SECS, default 20) — agents on slow VMs get to choose slow-success over fast-false-timeout.
    2. Keep 20 s but retry once at 45 s on timeout (costs up to 65 s worst case).
    3. Nothing — document that cookie writes prefer /sessions/load on weak environments.

    Not urgent: on healthy daemons (the normal case) everything passes.

  2. slabbdev commented on Oct 8, 2026

    @slabbdev
    OwnerAuthor

    Mitigation shipped in b3c24a0: (both backends, clamped [5, 300], default 20) — slow or contended environments choose slow-success over false-timeout. The refined diagnosis above stands: only under contention; healthy daemons never hit it.

  3. slabbdev commented on Oct 9, 2026

    @slabbdev
    OwnerAuthor

    Closing as upstream-wontfix, documented. Reproduced cleanly today (arm64 container, WebKitGTK + xvfb): document.cookie = … via evaluate hangs past 15 s on a REAL http origin (reads fine) — a WebKitGTK behavior when injected JS writes cookies against the ephemeral data store. The supported path is POST /sessions/load (WKWebsiteDataStore-level, works everywhere — every recipe in this repo uses it); evaluate stays read-only for cookies on Linux/macOS parity where it works. Reopen if an upstream WebKitGTK release changes this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions