joffrey-bion / krossbow

A Kotlin multiplatform coroutine-based STOMP client over websockets, with built-in conversions.
MIT License
195 stars 14 forks source link

Ktor WinHttp client echo tests fail with `JobCancellationException: Parent job is Cancelling` #466

Open joffrey-bion opened 6 months ago

joffrey-bion commented 6 months ago

This problem only occurs with the WinHttp client of the Ktor web socket implementation (thus only on Windows).

This exception surfaces when trying to assert the close frame during the echo binary and echo text tests (after the call to session.close()):

IllegalStateException: Unable to close WebSocket: The operation completed successfully. Error 0 (0x80070000)

This seems to be thrown here in the Ktor client: https://github.com/ktorio/ktor/blob/0a8cb15f6ff600decd6198d3f71bd39f9f482f0d/ktor-client/ktor-client-winhttp/windows/src/io/ktor/client/engine/winhttp/internal/WinHttpWebSocket.kt#L225

And getWinHttpException is defined as such: https://github.com/ktorio/ktor/blob/0a8cb15f6ff600decd6198d3f71bd39f9f482f0d/ktor-client/ktor-client-winhttp/windows/src/io/ktor/client/engine/winhttp/internal/WinHttpExceptions.kt#L23-L29

Which may explain the part The operation completed successfully, because we try to get the "last error" while there may have been none.


Extra traces during a test run (which helped figuring out the above summary):

KTOR onEach Binary emittedCloseFrame=false
KTOR onCompletion emittedCloseFrame=false error=kotlinx.coroutines.flow.internal.AbortFlowException: Flow was aborted, no more elements needed (cause=null)
KTOR close() closing... (isActive=true)
KTOR close() done (isActive=true)
KTOR onCompletion emittedCloseFrame=false error=kotlinx.coroutines.JobCancellationException: Parent job is Cancelling; job=JobImpl{Cancelled}@9d011b0 (cause=kotlin.IllegalStateException: Unable to close WebSocket: The operation completed successfully. Error 0 (0x80070000))
KTOR catch th=kotlinx.coroutines.JobCancellationException: Parent job is Cancelling; job=JobImpl{Cancelled}@9d011b0

kotlin.AssertionError: Expected Close frame (after echo binary), but the flow failed with org.hildan.krossbow.websocket.WebSocketException: error in Ktor's websocket: kotlinx.coroutines.JobCancellationException: Parent job is Cancelling; job=JobImpl{Cancelled}@9d011b0
kotlin.AssertionError: Expected Close frame (after echo binary), but the flow failed with org.hildan.krossbow.websocket.WebSocketException: error in Ktor's websocket: kotlinx.coroutines.JobCancellationException: Parent job is Cancelling; job=JobImpl{Cancelled}@9d011b0
    at kotlin.Error#<init>(Unknown Source)
    at kotlin.AssertionError#<init>(Unknown Source)
    at kotlin.test.DefaultAsserter#fail(Unknown Source)
    at kotlin.test.Asserter#fail(Unknown Source)
    at kotlin.test#fail(Unknown Source)
    at org.hildan.krossbow.websocket.test.expectCloseFrame$lambda$3$lambda$2#internal(Unknown Source)
        ...
joffrey-bion commented 6 months ago

Possible things to investigate:

joffrey-bion commented 5 months ago

I opened an issue to the Ktor team: https://youtrack.jetbrains.com/issue/KTOR-6845