Question: concurrent RSD connections to same device — anyone else seeing this?
What I'm seeing
When two processes open an RSD-based service connection to the same device at the same time, one of them fails during the RemoteXPC / HTTP/2 handshake with Connection was terminated abruptly. Staggering the two calls by ~100–300ms is enough to make both succeed. pymobiledevice3's default for syslog live goes through usbmuxd so this is invisible in normal usage — I only hit it when forcing RSD with --rsd HOST PORT.
Why I'm asking here
I first hit this in go-ios, which always auto-selects RSD on iOS 17+ whenever a tunnel is available. Two simultaneous calls there produce HTTP/2 RST INTERNAL_ERROR from the device. Since it looked like it might be client-side, I tried to reproduce with pymobiledevice3 forcing RSD — and got the same race with a slightly different error surface.
That leads me to think this is device-side behavior (the device's remoted rejecting two concurrent HTTP/2 handshakes on the RSD port), not something specific to either client library. But I'd love a sanity check before concluding that.
Questions
- Has anyone else run into this when running multiple concurrent pymobiledevice3 RSD-based sessions against the same device?
- Is there a known way to work around it beyond staggering calls or falling back to usbmuxd where possible?
- Is this already documented / reported to Apple somewhere I missed?
Environment
- pymobiledevice3: 9.8.1
- macOS: 26.4.1
- Device: iPhone, iOS 18.7.1
Reproducer
With a running tunnel, pick the RSD host + port and run two simultaneous syslog streams:
(timeout 3 pymobiledevice3 syslog live --rsd <addr> <port> 2>/tmp/p1.err > /tmp/p1.out) &
(timeout 3 pymobiledevice3 syslog live --rsd <addr> <port> 2>/tmp/p2.err > /tmp/p2.out) &
wait
wc -l /tmp/p1.out /tmp/p2.out
cat /tmp/p1.err /tmp/p2.err
Result:
0 /tmp/p1.out
6201 /tmp/p2.out
2026-04-14 09:57:16 mbal pymobiledevice3.__main__[49902] ERROR Connection was terminated abruptly
Which side wins is effectively random. Adding sleep 0.3 between the two launches makes both succeed reliably.
The equivalent test with go-ios through its RSD path fails similarly with readDataFrame: got RST frame with error code: INTERNAL_ERROR, which is the device emitting an HTTP/2 RST frame during the handshake.
Observations that back the device-side hypothesis
- Reproduces with two completely different clients (pymobiledevice3 and go-ios) that share no code
- Only reproduces on the RSD path; the same service (
com.apple.os_trace_relay) accessed over usbmuxd has no such issue even with many parallel clients
- Multiplexing many services inside one RemoteXPC session is fine — it's only the establishment of two independent sessions that races
- ~100ms stagger is enough to avoid it
Thanks for any pointers 🙏
Question: concurrent RSD connections to same device — anyone else seeing this?
What I'm seeing
When two processes open an RSD-based service connection to the same device at the same time, one of them fails during the RemoteXPC / HTTP/2 handshake with
Connection was terminated abruptly. Staggering the two calls by ~100–300ms is enough to make both succeed. pymobiledevice3's default forsyslog livegoes through usbmuxd so this is invisible in normal usage — I only hit it when forcing RSD with--rsd HOST PORT.Why I'm asking here
I first hit this in go-ios, which always auto-selects RSD on iOS 17+ whenever a tunnel is available. Two simultaneous calls there produce
HTTP/2 RST INTERNAL_ERRORfrom the device. Since it looked like it might be client-side, I tried to reproduce with pymobiledevice3 forcing RSD — and got the same race with a slightly different error surface.That leads me to think this is device-side behavior (the device's
remotedrejecting two concurrent HTTP/2 handshakes on the RSD port), not something specific to either client library. But I'd love a sanity check before concluding that.Questions
Environment
Reproducer
With a running tunnel, pick the RSD host + port and run two simultaneous syslog streams:
Result:
Which side wins is effectively random. Adding
sleep 0.3between the two launches makes both succeed reliably.The equivalent test with go-ios through its RSD path fails similarly with
readDataFrame: got RST frame with error code: INTERNAL_ERROR, which is the device emitting an HTTP/2 RST frame during the handshake.Observations that back the device-side hypothesis
com.apple.os_trace_relay) accessed over usbmuxd has no such issue even with many parallel clientsThanks for any pointers 🙏