diff --git a/.changeset/fix-byte-stream-source-leak.md b/.changeset/fix-byte-stream-source-leak.md new file mode 100644 index 00000000..36e59980 --- /dev/null +++ b/.changeset/fix-byte-stream-source-leak.md @@ -0,0 +1,5 @@ +--- +"client-sdk-android": patch +--- + +Fixed file descriptor leak in ByteStreamSender where Source was not closed after reading. diff --git a/livekit-android-sdk/src/main/java/io/livekit/android/room/datastream/outgoing/ByteStreamSender.kt b/livekit-android-sdk/src/main/java/io/livekit/android/room/datastream/outgoing/ByteStreamSender.kt index aa50ad74..95a7eb6d 100644 --- a/livekit-android-sdk/src/main/java/io/livekit/android/room/datastream/outgoing/ByteStreamSender.kt +++ b/livekit-android-sdk/src/main/java/io/livekit/android/room/datastream/outgoing/ByteStreamSender.kt @@ -86,25 +86,28 @@ suspend fun ByteStreamSender.write(input: InputStream): Result { /** * Reads the source and sends it to the data stream. + * + * The source will be closed when this function completes, whether it succeeds or fails. */ @CheckResult suspend fun ByteStreamSender.write(source: Source): Result { - val buffer = Buffer() - while (true) { - try { - val readLen = source.read(buffer, 4096) - if (readLen == -1L) { - break - } + return try { + source.use { src -> + val buffer = Buffer() + while (true) { + val readLen = src.read(buffer, 4096) + if (readLen == -1L) { + break + } - val result = write(buffer.readByteArray()) - if (result.isFailure) { - return result + val result = write(buffer.readByteArray()) + if (result.isFailure) { + return@use result + } } - } catch (e: Exception) { - return Result.failure(e) + Result.success(Unit) } + } catch (e: Exception) { + Result.failure(e) } - - return Result.success(Unit) }