I noticed this because in my uv branch, the close(handle) function acts as an "assert-unique-reference". This seemed to be working correctly in the successful case, but failing (with a dangling refcount of 2) in the case where an exception is thrown, and the handle is attempted to be closed in a finally block.
This is a similar issue to koka-lang/koka#854, however the koka compiler fix in koka-lang/koka#863 is not sufficient on its own.
The only combination of koka & async.kk which I've found to work correctly is:
output:
async finally: 0
async error: failed...
sync finally: 0
sync error: failed...
Using any other branch of koka or std results in the following incorrect output:
async finally: 2
async error: failed...
sync finally: 0
sync error: failed...
This implies that the refcount can leak either via lack of the improve-continuation-refcount, or by using the version of async.kk in both libuv-basics and koka-community/std/main (they're identical). It's not obvious what changes in my async-cancel branch cause this change in behaviour.
Test case:
import std/num/int32
import std/async/async
extern create-box(): io-noexn any
c inline "kk_cptr_raw_box(&kk_free_fun, kk_malloc(sizeof(int), _ctx), _ctx)"
extern get-refcount(^box: any): io-noexn int32
c inline "kk_block_refcount(kk_box_to_ptr(box, _ctx))"
fun main()
try (finalizer-async) fn(e)
println("async error: " ++ e.show)
0.int32
()
try (finalizer-sync) fn(e)
println("sync error: " ++ e.show)
0.int32
()
fun finalizer-async()
val box = create-box()
with finally {
println("async finally: " ++ box.get-refcount().show)
}
box-fail-async()
box.get-refcount()
fun finalizer-sync()
val box = create-box()
with finally {
println("sync finally: " ++ box.get-refcount().show)
}
box-fail-sync()
box.get-refcount()
fun failure()
Exception("failed...", ExnAssert)
fun box-fail-async()
val _: () = await1(fn(cb) -> cb(Error(failure()))).untry
()
fun box-fail-sync()
throw-exn(failure())
I noticed this because in my
uvbranch, theclose(handle)function acts as an "assert-unique-reference". This seemed to be working correctly in the successful case, but failing (with a dangling refcount of 2) in the case where an exception is thrown, and the handle is attempted to be closed in afinallyblock.This is a similar issue to koka-lang/koka#854, however the koka compiler fix in koka-lang/koka#863 is not sufficient on its own.
The only combination of
koka&async.kkwhich I've found to work correctly is:output:
Using any other branch of
kokaorstdresults in the following incorrect output:This implies that the refcount can leak either via lack of the
improve-continuation-refcount, or by using the version ofasync.kkin both libuv-basics and koka-community/std/main (they're identical). It's not obvious what changes in myasync-cancelbranch cause this change in behaviour.Test case: