[Bug] close() cancels DELETE request before it executes — resource leak on all platforms
Summary
When WebRTCSession.close() is called, the HTTP DELETE request to release the WHIP/WHEP resource is always cancelled before it can execute. This causes server-side resource leaks because the streaming session is never properly terminated.
Affected Platforms
- Android (
WebRTCSession.android.kt)
- JVM/Desktop (
WebRTCSession.jvm.kt)
- iOS (
WebRTCSession.ios.kt)
Library Version
syncai-lib-kmpwebrtc v2.1.0
Root Cause
In close(), the method calls cleanup(terminate = true). Inside cleanup():
scope.launch { signaling.terminate(resourceUrl) } — launches the HTTP DELETE on the session's CoroutineScope
- Immediately after,
scope.cancel() is called — cancelling the scope and all its children, including the just-launched DELETE coroutine
The DELETE never reaches the server.
Android (L295–314)
private fun cleanup(terminate: Boolean = false) {
if (terminate && resourceUrl != null) {
scope.launch { // ← launched on scope
signaling.terminate(resourceUrl!!)
}
}
// ... peer connection cleanup ...
scope.cancel() // ← immediately cancels scope
}
JVM (L261–280)
private fun cleanup(terminate: Boolean = false) {
if (terminate && resourceUrl != null) {
scope.launch { // ← launched on scope
signaling.terminate(resourceUrl!!)
}
}
// ... peer connection cleanup ...
scope.cancel() // ← immediately cancels scope
}
iOS (L281–300)
private fun cleanup(terminate: Boolean = false) {
if (terminate && resourceUrl != null) {
scope.launch { // ← launched on scope
signaling.terminate(resourceUrl!!)
}
}
// ... peer connection cleanup ...
scope.cancel() // ← immediately cancels scope
}
Expected Behavior
The HTTP DELETE request should complete successfully before the scope is cancelled, ensuring the server-side WHIP/WHEP resource is released.
Suggested Fix
Use an independent CoroutineScope for the DELETE request so it is not cancelled by scope.cancel():
Android / JVM
private fun cleanup(terminate: Boolean = false) {
if (terminate && resourceUrl != null) {
CoroutineScope(SupervisorJob() + Dispatchers.IO).launch {
try {
signaling.terminate(resourceUrl!!)
} catch (e: Exception) {
// log error
}
}
}
// ... peer connection cleanup ...
scope.cancel()
}
iOS
private fun cleanup(terminate: Boolean = false) {
if (terminate && resourceUrl != null) {
CoroutineScope(SupervisorJob() + Dispatchers.Default).launch {
try {
signaling.terminate(resourceUrl!!)
} catch (e: Exception) {
// log error
}
}
}
// ... peer connection cleanup ...
scope.cancel()
}
Impact
- Server resource leak: WHIP/WHEP sessions accumulate on the media server and are never cleaned up
- Port exhaustion: Unreleased sessions may hold server ports indefinitely
- Affects all callers: Any app using
WebRTCSession.close() is affected — there is no workaround at the app level
Steps to Reproduce
- Establish a WHIP or WHEP session via
WebRTCSession
- Call
close() on the session
- Observe server logs — no DELETE request is received for the resource URL
Additional Context
All three platform implementations (android, jvm, ios) share the identical bug pattern. The fix should be applied consistently across all three.
[Bug]
close()cancels DELETE request before it executes — resource leak on all platformsSummary
When
WebRTCSession.close()is called, the HTTP DELETE request to release the WHIP/WHEP resource is always cancelled before it can execute. This causes server-side resource leaks because the streaming session is never properly terminated.Affected Platforms
WebRTCSession.android.kt)WebRTCSession.jvm.kt)WebRTCSession.ios.kt)Library Version
syncai-lib-kmpwebrtcv2.1.0Root Cause
In
close(), the method callscleanup(terminate = true). Insidecleanup():scope.launch { signaling.terminate(resourceUrl) }— launches the HTTP DELETE on the session'sCoroutineScopescope.cancel()is called — cancelling the scope and all its children, including the just-launched DELETE coroutineThe DELETE never reaches the server.
Android (L295–314)
JVM (L261–280)
iOS (L281–300)
Expected Behavior
The HTTP DELETE request should complete successfully before the scope is cancelled, ensuring the server-side WHIP/WHEP resource is released.
Suggested Fix
Use an independent
CoroutineScopefor the DELETE request so it is not cancelled byscope.cancel():Android / JVM
iOS
Impact
WebRTCSession.close()is affected — there is no workaround at the app levelSteps to Reproduce
WebRTCSessionclose()on the sessionAdditional Context
All three platform implementations (
android,jvm,ios) share the identical bug pattern. The fix should be applied consistently across all three.