Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consumeEachBufferRange completes successfully on connection abort #1797

Open
fluidsonic opened this issue Apr 16, 2020 · 8 comments
Open

consumeEachBufferRange completes successfully on connection abort #1797

fluidsonic opened this issue Apr 16, 2020 · 8 comments
Assignees
Labels

Comments

@fluidsonic
Copy link
Contributor

fluidsonic commented Apr 16, 2020

Ktor Version and Engine Used
Ktor Client 1.3.2 with OkHttpClient 4.5.0 on Android 21

Describe the bug
When the connection dies during a streaming download, consumeEachBufferRange erroneously completes successfully.

To Reproduce

  1. I'm streaming a download using consumeEachBufferRange.
  2. When I turn on Airplane Mode during the download, the visitor I've passed to consumeEachBufferRange will be called with a buffer object that has 0 remaining bytes and last set to true. The latter, to my knowledge, indicates download completion.
  3. No IOException is thrown which further indicates that the download has completed.
  4. The download (consumeEachBufferRange invocations) isn't even close to the number of bytes indicated in the Content-Length header.

Note that it doesn't happen 100% of the time.
Sometimes I do get a shorter packet (e.g. 64 bytes instead of a typical 4088 byte packet) with last = false plus a SocketTimeoutException afterwards.

Expected behavior

  • consumeEachBufferRange shouldn't be called with a 0 byte buffer.
  • consumeEachBufferRange shouldn't be called with last = true for an aborted connection.
  • consumeEachBufferRange should throw an IOException for an aborted connection.
@fluidsonic fluidsonic added the bug label Apr 16, 2020
@dmitrievanthony dmitrievanthony self-assigned this Apr 20, 2020
@dmitrievanthony
Copy link
Contributor

dmitrievanthony commented Apr 20, 2020

Hi @fluidsonic,

I'm trying to reproduce the issue, but I always get java.net.ProtocolException: unexpected end of stream so far. Do you have some reproduced that I could use?

PS: I also tested it on Android where I got Exception: java.net.SocketException: Software caused connection abort.

@fluidsonic
Copy link
Contributor Author

I've tested on a Google Pixel 2 with Android 10 now (EDGE connection) and have the same problem there.

It seems to be related to the workaround for issue #1708 as I cannot reproduce it without retryOnConnectionFailure(true).

Test code:

HttpClient(OkHttp) {
   engine {
      config {
         retryOnConnectionFailure(true) // https://github.com/ktorio/ktor/issues/1708
      }
   }
}.use { httpClient ->
   httpClient
      .get<HttpStatement>("http://ipv4.download.thinkbroadband.com/5MB.zip")
      .execute { response ->
         val contentLength = response.contentLength()
         println("Response: ${response.status} with total length of $contentLength bytes.")

         var receivedBytes = 0L

         response.content.consumeEachBufferRange { buffer, last ->
            receivedBytes += buffer.remaining()
            println("Received ${buffer.remaining()} bytes ($receivedBytes of $contentLength total) (last = $last)")

            buffer.position(buffer.limit())

            true
         }

         println("Completed after receiving $receivedBytes of $contentLength.")
      }
}

Output:

Response: 200 OK with total length of 5242880 bytes.
Received 4088 bytes (4088 of 5242880 total) (last = false)
Received 4088 bytes (8176 of 5242880 total) (last = false)
Received 3084 bytes (11260 of 5242880 total) (last = true)
Completed after receiving 11260 of 5242880.

@dmitrievanthony
Copy link
Contributor

Thanks, @fluidsonic, I managed to reproduce it with retryOnConnectionFailure(true).

@dmitrievanthony
Copy link
Contributor

Well, I spent time trying to understand what's the reason and finally realized that the issue is not reproduced using the current ktor master branch, only version 1.3.2.

@fluidsonic
Copy link
Contributor Author

That's a good thing, I guess?

Is this bug actually unit-testable?
I have no idea how to simulate a network shutdown which triggers that issue.

@dmitrievanthony
Copy link
Contributor

Hi @fluidsonic,

I'm also not sure how to simulate this. An additional issue is that the behavior we'd like to test is reproduced only on Android.

@e5l e5l assigned e5l and unassigned dmitrievanthony May 21, 2020
@oleg-larshin
Copy link

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

@paderick
Copy link

This issue is still persistent on ktor 1.5.2

Any solutions for it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants