NEW322937
Automation.performInteractionSequence on iOS wedges the connection: next Automation command never gets a response
https://bugs.webkit.org/show_bug.cgi?id=322937
Summary Automation.performInteractionSequence on iOS wedges the connection: next Auto...
Mykola Mokhnach
Reported 2026-08-30 08:16:08 PDT
## Summary After a `Automation.performInteractionSequence` call completes successfully on iOS (Simulator, confirmed on iPhone 17 Pro / iOS 26.5), the *next* `Automation.*` command sent over the same WebDriver/webinspectord connection never receives a response - not an error, not a dropped connection, just silence forever. This happens with Apple's own `safaridriver`, so it isn't a third-party client bug. It reproduces with both `Mouse` and `Touch` `sourceType` (note: WebKit internally aliases `Mouse` to `Touch` on iOS anyway, per `WebAutomationSession::performInteractionSequence`, so this is really one code path). A 1 second delay before the next command does not avoid it - the connection is durably stuck, not caught in a brief race. In practice this means any WebDriver client that calls the W3C Actions API (`POST /session/:id/actions`) against Safari on iOS and then issues another command - including the standard follow-up `DELETE /session/:id/actions` (Release Actions) - can hang indefinitely and has no way to recover except tearing down and recreating the whole session. ## Environment - macOS 26.6.2 (build 25G83) - Xcode 26.6 (build 17F113) - Safari 26.6.2 (21624.5.1.11.3) / `safaridriver` (bundled) - iOS Simulator: iPhone 17 Pro, iOS 26.5 (build 23F77) - Also observed on iOS 27 beta Simulator and on a real iPad, via a WebDriver client using the same private `Automation` domain (not `safaridriver` - see Additional Notes) ## Steps to Reproduce 1. `safaridriver -p 5150 --diagnose` (`--diagnose` writes a full `Automation.*` protocol trace to `~/Library/Logs/com.apple.WebDriver/`, referenced below) 2. Boot an iOS Simulator, e.g. `xcrun simctl boot <udid>` for an iPhone 17 Pro / iOS 26.5 device, and launch Safari on it. 3. Create a session: ``` curl -s http://127.0.0.1:5150/session -d '{ "capabilities": { "alwaysMatch": { "browserName": "Safari", "platformName": "iOS", "safari:useSimulator": true, "safari:deviceUDID": "<simulator-udid>" } } }' ``` 4. Navigate to any page with a focusable/clickable element and interact with it a couple of times normally, e.g.: ``` curl -s http://127.0.0.1:5150/session/<id>/url -d '{"url": "<any page with a <textarea id=\"comments\">"}' curl -s http://127.0.0.1:5150/session/<id>/element -d '{"using": "css selector", "value": "#comments"}' # -> elementId curl -s http://127.0.0.1:5150/session/<id>/element/<elementId>/click -X POST curl -s http://127.0.0.1:5150/session/<id>/element/<elementId>/clear -X POST curl -s http://127.0.0.1:5150/session/<id>/element/<elementId>/value -d '{"text": "hello"}' ``` 5. Perform a W3C Actions pointer sequence against a *different* element on the page (`pointerType` can be `touch` or `mouse` - both reproduce it): ``` curl -s http://127.0.0.1:5150/session/<id>/actions -d '{ "actions": [{ "id": "finger1", "type": "pointer", "parameters": {"pointerType": "touch"}, "actions": [ {"type": "pointerMove", "duration": 0, "origin": {"element-6066-11e4-a52e-4f735466cecf": "<otherElementId>"}, "x": 0, "y": 0}, {"type": "pointerDown", "button": 0}, {"type": "pointerUp", "button": 0} ] }] }' ``` This returns `200 {"value": null}` normally. 6. Immediately release actions: ``` curl -s http://127.0.0.1:5150/session/<id>/actions -X DELETE ``` **Expected:** step 6 returns promptly, same as it does for any other session. **Actual:** step 6 never returns. Killing and restarting `safaridriver` does not fix it (a new session cannot even be created afterward until Safari itself is force-relaunched on the device/Simulator - the session appears permanently paired to the wedged one). The `--diagnose` log shows the outbound protocol message safaridriver sends for this HTTP request and no corresponding response ever arrives: ``` AutomationProtocol: SEND {"method":"Automation.performInteractionSequence", ... "inputSources":[{"sourceId":"finger1","sourceType":"Touch"}], ...}, "id":36} AutomationProtocol: RECV {"result":{},"id":36} HTTPServer: DELETE http://127.0.0.1:5150/session/<id>/actions AutomationProtocol: SEND {"method":"Automation.resolveBrowsingContext", "params":{"browsingContextHandle":"page-...","frameHandle":""},"id":37} <-- no RECV for id 37 ever arrives --> ``` This is `safaridriver`'s own internal `resolveBrowsingContext` preflight, sent as the first step of handling `DELETE /session/:id/actions`. I confirmed this specific handler (`WebAutomationSession::resolveBrowsingContext` in `Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp`) does no IPC round-trip to the WebContent process at all - it's fully synchronous UIProcess-side code (`webPageProxyForHandle` + `webFrameIDForHandle`, then `callback({})`). If it never answers, the stall is upstream of this handler entirely - somewhere in whatever routes the incoming Automation command to it (or serializes its response back out) after a `performInteractionSequence` call completes. I reproduced this identically twice, once with `sourceType: "Mouse"` and once with `sourceType: "Touch"` in the actions payload - full diagnostic traces for both available on request. ## Additional Notes - Not argument-related: I compared the request shape against two independent open-source WebDriver/remote-debugging client implementations (`go-ios`, `pymobiledevice3`) that talk to this same private protocol, and against `safaridriver`'s own requests - all send `performInteractionSequence` with the same `handle`/`inputSources`/`steps` shape. - Not `pointerType`-specific: reproduced with both `Mouse` and `Touch`. This is expected given `WebAutomationSession::performInteractionSequence` aliases `Mouse`/`Pen` to `Touch` on platforms without `WEBDRIVER_MOUSE_INTERACTIONS` (iOS). - Not a brief race: inserting a 1 second delay before the `DELETE /session/:id/actions` call did not avoid the hang. - Not always reproducible: a simpler self-contained `data:` URL page with a single `<button>`, clicked once and then driven through the same actions+release sequence, did *not* reproduce the hang in a few attempts - only a real HTTP-served page with prior interaction on a *different* element did. I was not able to narrow this down further; it may be relevant that the page that reproduces it consistently also logs a couple of JavaScript console errors on load (undefined variable references), or that scrolling/layout state differs between the two pages. - No corresponding crash report or unified-log error was found for `WebProcess`/`Safari`/`webinspectord` around the hang - the process does not crash, it simply stops answering. - Downstream impact: this affects any Automation-domain WebDriver client (e.g. Appium's `appium-remote-debugger`), not just `safaridriver` - we hit the identical wedge independently before reproducing it here.
Attachments
Mykola Mokhnach
Comment 1 2026-08-30 08:31:10 PDT
The page I used for testing: https://saucelabs.com/test/guinea-pig
Radar WebKit Bug Importer
Comment 2 2026-09-06 08:17:12 PDT
Note You need to log in before you can comment on or make changes to this bug.