Serious bug in the JDK7 support library

I’m posting here because I’m not sure where I should post such bug report concerning the kotlinx support library. Please direct me to the proper bug tracker and I’ll be sure to post it there.

In the meantime, the bug being a pernicious one, it may be useful to warn other developpers :wink:

This code does not close the resource:

class Ressource() : AutoCloseable {
    override fun close() {
        println("Closing")
    }
}

fun test(): String {
    Ressource().use {
        return "Hello, world!"
    }
}

fun main(args: Array<String>) {
    println(test())
}

When running this code, “Hello, world!” is printed but never “Closing”.

If I replace the test function by this, it works (note the difference in the placement of return):

fun test(): String {
    return Ressource().use {
        "Hello, world!"
    }
}

This is because of the way the use function is declared in the kotlinx.support library:

public inline fun <T : AutoCloseable, R> T.use(block: (T) -> R): R {
    val result = try {
        block(this)
    } catch (e: Throwable) {
        closeSuppressed(e)
        throw e
    }
    close()
    return result
}

Because it is an inline function, non-local returns are allowed in the “block” lambda. In case of such a return, the close code will never be executed.

The kotlin-stdlib uses a try-finally construct that ensure that, even in the case of a non-local return, the resource will be properly closed.

In my opinion, this is a very critical bug, because:

  • it enables the possibility of exiting the use block without closing the resource, which is precisely what use is supposed to prevent.
  • It behaves differently than the kotlin-stdlib version of Closeable.use.
  • It took me two hours to debug :stuck_out_tongue:
1 Like

Thanks for the report, I’ll investigate the issue.
I’ll post updates to the similar issue on github: AutoCloseable.use must be implemented using try-finally · Issue #3 · Kotlin/kotlinx.support · GitHub