I am running calling a native function in Kotlin that takes a Unix file descriptor as a parameter. After the native function runs for a few minutes it report EBADF.
The code looks something like
class A(val file: ParcelFileDescriptor) : AutoCloseable {
private var fileDes: Int = -1
private external fun longRunningNativeFn(fd : Int) : FnResult
init {
fileDes = file.fd
}
fun process() : FnResult {
longRunningNativeFn(fileDes)
}
override fun close {
}
}
The file object passed into the constructor is not held anywhere else.
My working theory is that since file
is only used in the init
block, file
then becomes a candidate for garbage collection so after a few minutes when the garbage collector kicks in, the file
object calls close resulting in the native code getting a bad file descriptor.
So
- is this theory correct?
- If so what determines the lifetime of parameters in the constructor?
- Does adding
file.close()
to theclose
function extend the lifetime offile
for the duration of the class?
Note after adding the file.close()
, I am no longer getting the BADF in my native code. Even though as @Ivo points out adding val to the primary constructor makes file
a class member, the JRE might be smart enough to see nothing is using file
and garbage collect it early since it needs to stick around until close
is called