Skip to content

Concurrent RSD/tunnel sessions fail (RST / STREAM_CLOSED) #724

Description

@danielpaulus

Summary

Two concurrent RSD/tunnel sessions to the same device fail. When one command holds an RSD session open (e.g. ios devicestate enable, which keeps a condition active until it receives SIGTERM), a second command that opens its own RSD session (e.g. ios devicestate list, ios info display, ios ps) fails to connect with an RST / STREAM_CLOSED error — or, intermittently, the second command "succeeds" but the state operation behaves as if it never connected.

Steps to reproduce

With the tunnel running (ios tunnel start), Developer Mode on, and a DDI mounted (iOS 17+):

# Terminal 1 — holds an RSD/instruments session open
ios devicestate enable SlowNetworkCondition SlowNetwork3GGood --udid=$UDID

# Terminal 2 — a second RSD command while the first is running
ios devicestate list --udid=$UDID

Actual result

The second command fails:

{"err":"newRsdServiceFromTcpConn: failed to create xpc connection: CreateXpcConnection: failed to initialize xpc connection: initializeXpcConnection: failed to decode message: DecodeMessage: failed to read magic number: ReadClientServerStream: readDataFrame: got RST frame with error code: STREAM_CLOSED","level":"fatal","msg":"could not connect to RSD, host fd23:4326:be9c::1, port 49911"}

On macOS it sometimes manifests differently: the second command connects but the operation does not reflect reality (e.g. devicestate list reports IsActive=false even though the condition is active).

Expected result

Concurrent RSD-based commands against the same device/tunnel should work, or at least fail gracefully / queue, rather than resetting the stream.

Notes

  • Reproduced on both macOS and Linux self-hosted runners.
  • iOS 18.4.1 (iPhone14,2) and iOS 18.5 (iPhone15,2).
  • Tunnel created via ios tunnel start (kernel tunnel).
  • Interestingly, spacing the commands out by a few seconds and only issuing the second one once often works, so it looks like a race/contention in establishing a second RSD/XPC session rather than a hard "only one session ever" limit.

Impact

Makes it hard to verify state-mutating tunnel commands by querying device state from a separate process while the setter holds its session (e.g. confirming devicestate enable took effect via a concurrent devicestate list). A workaround is to read the setter command's own output instead of issuing a concurrent query.

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