hi
suspend fun ServerSocket.listening() = suspendCancellableCoroutine<Socket> {
it.resume(accept())
it.invokeOnCancellation { println("coroutine is canceling...."); close() }
}
fun main() = runBlocking {
val job = launch {
val server = ServerSocket(3000)
server.listening()
}
delay(3000)
job.cancel()
}
i expected after 3 sec coroutine is cancelled and throws an cancellationexception and server is close but not think happen and server still running after 3 sec
accept if a blocking function. You cannot cancel it this way. Cancellation in coroutines in cooperative as explained here: https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html
Does it help?
thanks
val job = launch {
val server = ServerSocket(3000)
//server.listening()
while(isActive) {
server.accept()
}
}
if i understand carfully docs accept() deos not enable the check of coroutine cancellation (isActive) even if the job was canceled, so in this case (with methods blocking like accept()) how we can cancel coroutine and in wich case suspendCancellableCoroutine is useful ??
thanks
Yes. accept() is a blocking method and it does not support cancellation.
@halimpuckjava
What about something like this:
val SocketException.socketHasBeenClosed : Boolean get() = TODO()
suspend fun ServerSocket.listening() = suspendCancellableCoroutine<Socket> {
it.invokeOnCancellation { try { close() } catch (e: Throwable){} }
thread {
try {
it.resume(accept())
} catch (e: SocketException) {
if (e.socketHasBeenClosed) {
it.cancel()
}
else {
it.resumeWithException(e)
}
}
}
}
(instead of thread { .... }, you may want to use a pool of threads instead, like from an ExecutorService)
If you want to make a non-blocking use of accept you don't need to create a thread yourself, just do this:
withContext(Dispatchers.IO) {
socket.accept()
}
This way the caller is not going to be blocked. However, it will not be cancellable. Indeed, you can make it "cancellable" by closing socket on cancelled. There is not way to abort accept(), yet keep the socket open. You need asynchronous API (like java.nio) for that.
thanks,