@@ -27,6 +27,7 @@ import org.jitsi.utils.logging2.Logger
2727import org.jitsi.utils.logging2.createChildLogger
2828import org.jitsi.videobridge.sctp.SctpConfig
2929import org.jitsi.videobridge.util.TaskPools
30+ import java.lang.ref.WeakReference
3031import java.time.Clock
3132import java.time.Instant
3233import java.util.concurrent.Future
@@ -109,7 +110,7 @@ abstract class DcSctpBaseCallbacks(
109110) : DcSctpSocketCallbacks {
110111 /* Methods we can usefully implement for every JVB socket */
111112 override fun createTimeout (p0 : DcSctpSocketCallbacks .DelayPrecision ): Timeout {
112- return ATimeout ()
113+ return ATimeout (transport )
113114 }
114115
115116 override fun Now (): Instant {
@@ -142,7 +143,11 @@ abstract class DcSctpBaseCallbacks(
142143 transport.logger.info(" Surprising SCTP callback: incoming streams ${incomingStreams.joinToString()} reset" )
143144 }
144145
145- private inner class ATimeout : Timeout {
146+ private class ATimeout (transport : DcSctpTransport ) : Timeout {
147+ // This holds a weak reference to the transport, to break JNI reference cycles
148+ private val weakTransport = WeakReference (transport)
149+ private val transport: DcSctpTransport ?
150+ get() = weakTransport.get()
146151 private var timeoutId: Long = 0
147152 private var scheduledFuture: ScheduledFuture <* >? = null
148153 private var future: Future <* >? = null
@@ -152,11 +157,11 @@ abstract class DcSctpBaseCallbacks(
152157 scheduledFuture = TaskPools .SCHEDULED_POOL .schedule({
153158 /* Execute it on the IO_POOL, because a timer may trigger sending new SCTP packets. */
154159 future = TaskPools .IO_POOL .submit {
155- transport.socket.handleTimeout(timeoutId)
160+ transport? .socket? .handleTimeout(timeoutId)
156161 }
157162 }, duration, TimeUnit .MILLISECONDS )
158163 } catch (e: Throwable ) {
159- transport.logger.warn(" Exception scheduling DCSCTP timeout" , e)
164+ transport? .logger? .warn(" Exception scheduling DCSCTP timeout" , e)
160165 }
161166 }
162167
0 commit comments