This is an automated email from the ASF dual-hosted git repository.
raulcd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 24823829e0e GH-50597: [CI] Retry Chrome PyArrow load and fix Snappy
Emscripten configure (#50598)
24823829e0e is described below
commit 24823829e0e0378a08cbb1a3292573c97e56fda3
Author: tadeja <[email protected]>
AuthorDate: Fri Jul 24 10:59:29 2026 +0200
GH-50597: [CI] Retry Chrome PyArrow load and fix Snappy Emscripten
configure (#50598)
### Rationale for this change
Fix #50597. Nightly Crossbow job `test-conda-python-emscripten` sometimes
finishes with success like [2026-07-18 Docker Test
conda-python-emscripten](https://github.com/ursacomputing/crossbow/actions/runs/29628907267/job/88038728709#step:6:7261)
But often hangs like [2026-07-19 Docker Test
conda-python-emscripten](https://github.com/ursacomputing/crossbow/actions/runs/29672419322/job/88153721397#step:6:6851)
and [2026-07-20 Docker Test
conda-python-emscripten](https://github.com/ursacomputing/crossbow/actions/runs/29715959996/job/88269203693#step:6:6846)
```
driver.load_arrow()
...
selenium.common.exceptions.TimeoutException: Message: script timeout
```
Additionally, main nightly started failing during `snappy_ep` configure
with CMake 4.4: `CMake Error: The warning category "linkflags" is not known.`
### What changes are included in this PR?
import `TimeoutException`, introduce 300s timeout + 3 attempts around
load_arrow() and full Chrome restart on timeout,
ignore harmless `BrokenPipeError` / `ConnectionResetError` when Chrome has
to be killed mid-download for retry.
Also remove the redundant standalone `-Wno-error=linkflags` CMake argument
from Snappy's Emscripten configure arguments. The flag remains in
`CMAKE_SHARED_LINKER_FLAGS`
### Are these changes tested?
Yes, locally by `docker compose run --rm -e
SETUPTOOLS_SCM_PRETEND_VERSION=26.0.0.dev0 conda-python-emscripten`.
Example test run hit the PyArrow load timeout once, restarted Chrome, and
then completed successfully.
### Are there any user-facing changes?
No.
* GitHub Issue: #50597
Authored-by: Tadeja Kadunc <[email protected]>
Signed-off-by: Raúl Cumplido <[email protected]>
---
cpp/cmake_modules/ThirdpartyToolchain.cmake | 3 +-
python/scripts/run_emscripten_tests.py | 49 ++++++++++++++++++++++++-----
2 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/cpp/cmake_modules/ThirdpartyToolchain.cmake
b/cpp/cmake_modules/ThirdpartyToolchain.cmake
index 1677b188b9f..c34bd87edd7 100644
--- a/cpp/cmake_modules/ThirdpartyToolchain.cmake
+++ b/cpp/cmake_modules/ThirdpartyToolchain.cmake
@@ -1451,8 +1451,7 @@ macro(build_snappy)
# ignore linker flag errors, as Snappy sets
# -Werror -Wall, and Emscripten doesn't support -soname
list(APPEND SNAPPY_CMAKE_ARGS
- "-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}"
- "-Wno-error=linkflags")
+ "-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}")
endif()
externalproject_add(snappy_ep
diff --git a/python/scripts/run_emscripten_tests.py
b/python/scripts/run_emscripten_tests.py
index 002698a77e2..9ac3e0d8d7f 100644
--- a/python/scripts/run_emscripten_tests.py
+++ b/python/scripts/run_emscripten_tests.py
@@ -31,9 +31,18 @@ from pathlib import Path
from io import BytesIO
from selenium import webdriver
+from selenium.common.exceptions import TimeoutException
class TemplateOverrider(http.server.SimpleHTTPRequestHandler):
+ def handle(self):
+ try:
+ super().handle()
+ except (BrokenPipeError, ConnectionResetError):
+ # Browser restart while downloading wheel closes connection
+ # before server response is written so ignore harmless errors
+ pass
+
def log_request(self, code="-", size="-"):
# don't log successful requests but log errors
if isinstance(code, int) and code >= 400:
@@ -200,8 +209,9 @@ class NodeDriver:
class BrowserDriver:
def __init__(self, hostname, port, driver):
+ self.url = f"http://{hostname}:{port}/test.html"
self.driver = driver
- self.driver.get(f"http://{hostname}:{port}/test.html")
+ self.driver.get(self.url)
# Chrome on CI takes longer than locally to compile.
self.driver.set_script_timeout(1200)
@@ -209,10 +219,25 @@ class BrowserDriver:
pass
def load_arrow(self):
- self.execute_python(
- f"import pyodide_js as pjs\n"
- f"await pjs.loadPackage('{PYARROW_WHEEL_PATH.name}')\n"
- )
+ code = (f"import pyodide_js as pjs\n"
+ f"await pjs.loadPackage('{PYARROW_WHEEL_PATH.name}')\n")
+ for attempt in range(3):
+ # Set temporary timeout each attempt as Chrome restart creates a
driver
+ self.driver.set_script_timeout(300)
+ try:
+ self.execute_python(code)
+ except TimeoutException:
+ if attempt == 2:
+ raise
+ print("Timed out loading PyArrow in browser. Restarting
browser",
+ flush=True)
+ self.restart_browser()
+ else:
+ self.driver.set_script_timeout(1200)
+ return
+
+ def restart_browser(self):
+ self.driver.get(self.url)
def execute_python(self, code, wait_for_terminate=True):
if wait_for_terminate:
@@ -256,7 +281,8 @@ class BrowserDriver:
class ChromeDriver(BrowserDriver):
- def __init__(self, hostname, port):
+ @staticmethod
+ def _make_driver():
from selenium.webdriver.chrome.options import Options
options = Options()
@@ -264,7 +290,16 @@ class ChromeDriver(BrowserDriver):
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(options=options)
driver.command_executor._client_config.timeout = 1200
- super().__init__(hostname, port, driver)
+ return driver
+
+ def __init__(self, hostname, port):
+ super().__init__(hostname, port, self._make_driver())
+
+ def restart_browser(self):
+ self.driver.quit()
+ self.driver = self._make_driver()
+ self.driver.get(self.url)
+ self.driver.set_script_timeout(1200)
class FirefoxDriver(BrowserDriver):