mirror of
https://github.com/unslothai/unsloth.git
synced 2026-05-17 03:56:07 +00:00
ci(mac): single-process Chromium + JSON.parse try/catch in pipeTransport
Run 25491698868 / job 74801076186 hit the Playwright pipeTransport 'Unexpected end of JSON input' crash on ALL THREE retry attempts (at 11:00:52, 11:01:07, 11:01:21 — only ~15s apart). The retry-with- Studio-reset wrapper fromd35bf6acouldn't recover because the crash hits 100% of attempts on this run, not as a rare race. Two complementary fixes: 1. tests/studio/playwright_chat_ui.py + playwright_extra_ui.py: pass --single-process / --no-sandbox / --disable-dev-shm-usage / --disable-gpu to chromium.launch. --single-process is the key one: it keeps the renderer in the browser process, eliminating the browser↔renderer IPC pipe that was the actual crash site (Chromium's renderer was dying mid-startup and corrupting the pipe stream the Node driver was parsing). 2. .github/workflows/studio-mac-ui-smoke.yml: backport upstream Playwright's try/catch around the two JSON.parse(message) sites in driver/.../pipeTransport.js so a malformed stdout chunk (e.g. empty buffer between two \0 delimiters) is dropped silently instead of throwing and killing the entire Node driver. Newer Playwright versions ship this guard upstream; we patch it in via a python script after `playwright install chromium` so the fix lives only in CI's Mac job. Idempotent: prints "no matches; skipping" if upstream changes the pattern. The retry loop fromd35bf6ais kept as a third line of defense for any residual Chromium-died-and-stayed-dead scenarios.
This commit is contained in:
parent
a810e8fbbb
commit
fdf7f94f46
3 changed files with 71 additions and 7 deletions
42
.github/workflows/studio-mac-ui-smoke.yml
vendored
42
.github/workflows/studio-mac-ui-smoke.yml
vendored
|
|
@ -93,15 +93,47 @@ jobs:
|
|||
# needs already.
|
||||
# Pinned <1.58 because all 1.55-1.58 drivers ship Node 24 on
|
||||
# macos-14 and intermittently hit 'SyntaxError: Unexpected end
|
||||
# of JSON input' in pipeTransport.js when the Chromium child
|
||||
# transiently flushes an empty buffer. The crash is racy and
|
||||
# only triggers on a fraction of runs; the retry wrapper in
|
||||
# "Drive the chat UI with Playwright" is what actually keeps
|
||||
# the job green when the race fires.
|
||||
# of JSON input' in pipeTransport.js. Run 25491698868 showed
|
||||
# the crash hitting 100% of three retry attempts -- not a
|
||||
# rare race but a hard reproduction. Belt-and-suspenders fix:
|
||||
# the test scripts pass --single-process to Chromium (see
|
||||
# tests/studio/playwright_chat_ui.py) AND we patch
|
||||
# pipeTransport.js below to swallow JSON parse errors instead
|
||||
# of crashing the driver Node process. Both together let the
|
||||
# in-script retry recover from any residual flakes.
|
||||
run: |
|
||||
pip install 'playwright>=1.55,<1.58'
|
||||
python -m playwright install chromium
|
||||
|
||||
- name: Patch Playwright pipeTransport.js to tolerate malformed JSON
|
||||
# In Playwright 1.55-1.58, pipeTransport.js does
|
||||
# `JSON.parse(message)` with no try/catch; when Chromium dies
|
||||
# mid-write the partial buffer crashes the driver Node
|
||||
# process and the test script exits with 'Connection closed
|
||||
# while reading from the driver'. Newer Playwright versions
|
||||
# added a try/catch upstream. Backport that here.
|
||||
run: |
|
||||
python - <<'PY'
|
||||
import os, re, sys
|
||||
import playwright
|
||||
driver_dir = os.path.join(os.path.dirname(playwright.__file__), "driver", "package", "lib", "server")
|
||||
path = os.path.join(driver_dir, "pipeTransport.js")
|
||||
src = open(path).read()
|
||||
# Wrap both `this.onmessage.call(null, JSON.parse(...))` sites in try/catch.
|
||||
patched = re.sub(
|
||||
r"this\.onmessage\.call\(null, JSON\.parse\((message2?)\)\);",
|
||||
r"try { this.onmessage.call(null, JSON.parse(\1)); } "
|
||||
r"catch (e) { /* swallow malformed JSON from a crashing browser */ }",
|
||||
src,
|
||||
)
|
||||
if patched == src:
|
||||
# Already patched, or upstream changed -- either way, don't fail the build.
|
||||
print(f"pipeTransport.js: no JSON.parse calls matched at {path}; skipping.")
|
||||
else:
|
||||
open(path, "w").write(patched)
|
||||
print(f"pipeTransport.js: patched JSON.parse calls in {path}")
|
||||
PY
|
||||
|
||||
- name: Reset auth + boot Studio
|
||||
run: |
|
||||
unsloth studio reset-password
|
||||
|
|
|
|||
|
|
@ -118,7 +118,26 @@ def parse_rgb(s):
|
|||
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless = True)
|
||||
# Chromium stability args for macos-14 free runners. Without these
|
||||
# Chromium browser process dies in the first few seconds (during
|
||||
# change-password page load) and the driver Node process can't
|
||||
# parse the truncated stdout JSON-RPC line, throwing
|
||||
# 'SyntaxError: Unexpected end of JSON input' in pipeTransport.js
|
||||
# — see runs 25491698868 / 25489049059. --disable-dev-shm-usage and
|
||||
# --no-sandbox are the standard set; --disable-gpu forces software
|
||||
# rendering on the headless runner; --single-process keeps the
|
||||
# renderer in the same process as the browser, eliminating the
|
||||
# browser↔renderer IPC pipe that was the actual crash site.
|
||||
_CHROMIUM_STABILITY_ARGS = [
|
||||
"--disable-dev-shm-usage",
|
||||
"--no-sandbox",
|
||||
"--disable-gpu",
|
||||
"--single-process",
|
||||
]
|
||||
browser = p.chromium.launch(
|
||||
headless = True,
|
||||
args = _CHROMIUM_STABILITY_ARGS,
|
||||
)
|
||||
ctx = browser.new_context(
|
||||
viewport = {"width": 1280, "height": 900},
|
||||
# Reduces motion so the theme toggle's view-transition
|
||||
|
|
|
|||
|
|
@ -81,7 +81,20 @@ def runtime_warn(m: str) -> None:
|
|||
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless = True)
|
||||
# Chromium stability args -- same set as playwright_chat_ui.py.
|
||||
# Without these Chromium dies in the first seconds on macos-14
|
||||
# free runners and pipeTransport.js throws
|
||||
# 'SyntaxError: Unexpected end of JSON input'.
|
||||
_CHROMIUM_STABILITY_ARGS = [
|
||||
"--disable-dev-shm-usage",
|
||||
"--no-sandbox",
|
||||
"--disable-gpu",
|
||||
"--single-process",
|
||||
]
|
||||
browser = p.chromium.launch(
|
||||
headless = True,
|
||||
args = _CHROMIUM_STABILITY_ARGS,
|
||||
)
|
||||
ctx = browser.new_context(
|
||||
viewport = {"width": 1280, "height": 900},
|
||||
reduced_motion = "reduce",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue