From 793df5a91a51b253c75dd0b2ab9045fd4d05e230 Mon Sep 17 00:00:00 2001 From: Jonathan Lennox Date: Fri, 21 Jun 2024 14:40:09 -0400 Subject: [PATCH] Fix(dcsctp): Fix memory leak. (#2182) There were reference cycles through JNI, which the garbage collector can't detect. --- jvb/pom.xml | 2 +- .../org/jitsi/videobridge/dcsctp/DcSctpTransport.kt | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/jvb/pom.xml b/jvb/pom.xml index f50e07fb3c..1aeab10a92 100644 --- a/jvb/pom.xml +++ b/jvb/pom.xml @@ -113,7 +113,7 @@ ${project.groupId} jitsi-dcsctp - 1.0-2-g2d8eee4 + 1.0-3-gaf9d564 diff --git a/jvb/src/main/kotlin/org/jitsi/videobridge/dcsctp/DcSctpTransport.kt b/jvb/src/main/kotlin/org/jitsi/videobridge/dcsctp/DcSctpTransport.kt index 8269c5c76a..07d64f9343 100644 --- a/jvb/src/main/kotlin/org/jitsi/videobridge/dcsctp/DcSctpTransport.kt +++ b/jvb/src/main/kotlin/org/jitsi/videobridge/dcsctp/DcSctpTransport.kt @@ -27,6 +27,7 @@ import org.jitsi.utils.logging2.Logger import org.jitsi.utils.logging2.createChildLogger import org.jitsi.videobridge.sctp.SctpConfig import org.jitsi.videobridge.util.TaskPools +import java.lang.ref.WeakReference import java.time.Clock import java.time.Instant import java.util.concurrent.Future @@ -109,7 +110,7 @@ abstract class DcSctpBaseCallbacks( ) : DcSctpSocketCallbacks { /* Methods we can usefully implement for every JVB socket */ override fun createTimeout(p0: DcSctpSocketCallbacks.DelayPrecision): Timeout { - return ATimeout() + return ATimeout(transport) } override fun Now(): Instant { @@ -142,7 +143,11 @@ abstract class DcSctpBaseCallbacks( transport.logger.info("Surprising SCTP callback: incoming streams ${incomingStreams.joinToString()} reset") } - private inner class ATimeout : Timeout { + private class ATimeout(transport: DcSctpTransport) : Timeout { + // This holds a weak reference to the transport, to break JNI reference cycles + private val weakTransport = WeakReference(transport) + private val transport: DcSctpTransport? + get() = weakTransport.get() private var timeoutId: Long = 0 private var scheduledFuture: ScheduledFuture<*>? = null private var future: Future<*>? = null @@ -152,11 +157,11 @@ abstract class DcSctpBaseCallbacks( scheduledFuture = TaskPools.SCHEDULED_POOL.schedule({ /* Execute it on the IO_POOL, because a timer may trigger sending new SCTP packets. */ future = TaskPools.IO_POOL.submit { - transport.socket.handleTimeout(timeoutId) + transport?.socket?.handleTimeout(timeoutId) } }, duration, TimeUnit.MILLISECONDS) } catch (e: Throwable) { - transport.logger.warn("Exception scheduling DCSCTP timeout", e) + transport?.logger?.warn("Exception scheduling DCSCTP timeout", e) } }