ktor: ktor websocket client crashes with java.io.IOException: Software caused connection in Android abort
Version: 1.2.2, client, io.ktor:ktor-client-cio, io.ktor:ktor-client-websockets Android 7.0
When using websocket client
To Reproduce code:
val uri = URLBuilder().takeFrom(configuration.url).build()
val httpClientEngine = CIO.create { }
val client = HttpClient(httpClientEngine).config {
install(WebSockets)
}
suspend fun process(session: DefaultClientWebSocketSession): ConnectionStatus {
while (session.isActive && !session.closeReason.isCompleted) {
try {
select<Unit> {
session.incoming.onReceiveOrNull { frame ->
when (frame) {
null -> { // channel has been closed
println("closed")
session.close()
}
else -> Unit
}
}
}
} catch (e: IOException) {
println("io exception: ${e}")
session.close()
} catch (e: Throwable) {
println("exception: ${e}")
session.close()
}
}
}
runBlocking {
try {
when (uri.protocol.isSecure()) {
true -> client.wss(host = uri.host, port = uri.port, path = uri.encodedPath) { process(this) }
false -> client.ws(host = uri.host, port = uri.port, path = uri.encodedPath) { process(this) }
}
} catch (ex: Exception) {
println("catched: ${ex}")
}
}
- Start code with internet enabled and with some websocket url
- disconnect internet IOException will be thrown, but not caught anywhere.
Expected behavior I’m expecting that this IOException won’t leak and can be caught by try/catch.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 7
- Comments: 16 (3 by maintainers)
Commits related to this issue
- Use okhttp engine for java instead of cio workaround https://github.com/ktorio/ktor/issues/1237 — committed to luca992/kEasySocket by luca992 5 years ago
- Prevent propagating exception to top-level Fix #1356 #1237 — committed to ktorio/ktor by e5l 4 years ago
- Prevent propagating exception to top-level Fix #1356 #1237 — committed to ktorio/ktor by e5l 4 years ago
Investigation history:
maybe problem is here:
Socket.tls(coroutineContext: CoroutineContext, config: TLSConfig)
function:val reader = openReadChannel()
attachForReading(channel: ByteChannel): WriterJob
CoroutineScope.attachForReadingDirectImpl(...)
// <— this is implemented in internal abstract class NIOSocketImpl<out S> with CoroutineScopewriter(Dispatchers.Unconfined, channel) { .. block .. }
tls()
nor ktor CIO context, this just runs on Dispatchers.Default with Job() So there is no way to catch this exception and its bubbled to global exception handler.We are still waiting while ktor team will fix this critical bug which was introduced in some versions later and never got fixed. This bug cause crashes not only android but also server side thus making multiplatform websockets unusable.
On 2020-01-12, Sun at 21:03, David Alan Cohen notifications@github.com wrote:
This may not be applicable to every application that is running into this issue, but if you want to swallow this
IOException
so that the app doesn’t fatally crash, you can override the thread’s default exception handler with custom behavior usingThread.setDefaultUncaughtExceptionHandler()
inMainActivity.onCreate()
.I think it’s not reliable solution, maybe with this fix probability of crash will be lower, but not impossible, as by looking inside the ktor’s code there is no way to handle exception if it will be thrown during non blocking socket read.
No, currently there is no way to use ktor websockets in android platform to prevent crash. We’ve temporarily removed websocket from our app as it was used only for telemetry data.
I had hope that this will be fixed with latest release, but seems it’s not trivial to fix.
On Mon, 5 Aug 2019 at 13:29, Saddam Asmatullayev notifications@github.com wrote: