question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Apache HTTP Client often hangs forever (deadlocks) in async block

See original GitHub issue

Ktor Version

1.0.0

Ktor Engine Used(client or server and name)

Apache HTTP Client

JVM Version, Operating System and Relevant Context

Oracle JDK 1.8.0_161-b12 (same issue on OpenJDK 8) OS: Windows 10, 64bit

Feedback

When running the Apache HTTP client (through the ktor client API), the client sometimes just “freezes” and hangs indefinitly, sending the application into a deadlock. This effect is very noticeable when calling the client from an async block.

Please consider the following self-contained JUnit test:

import io.ktor.client.HttpClient
import io.ktor.client.engine.apache.Apache
import io.ktor.client.engine.cio.CIO
import io.ktor.client.request.get
import kotlinx.coroutines.*
import org.junit.Test

class CoroutineTest {

    @Test
    fun testWithGlobalScope(){
        println("WITH GLOBAL SCOPE")
        runBlocking {
            runTest(GlobalScope)
        }
    }

    @Test
    fun testWithCoroutineScope(){
        println("WITH COROUTINE SCOPE")
        runBlocking {
            runTest(this)
        }
    }

    @Test
    fun testWithIndependentScope(){
        println("WITH BLOCK SCOPE")
        runBlocking {
            coroutineScope{
                runTest(this)
            }
        }
    }

    private suspend fun runTest(scope: CoroutineScope): Int{
        // retrieve number of CPU cores
        var sum = 0
        val tasks = mutableListOf<Deferred<Int>>()
        for(i in 0 until 50){
            println("Launching async task #${i+1}")
            tasks += scope.async {
                val client = HttpClient(Apache)
                try{
                    log("HTTP client open. Performing GET")
                    val string = client.get<String>("https://www.google.com")
                    log("GET result received: ${string.replace("\r?\n", " ").substring(0, 20)}...")
                }finally{
                    log("Closing HTTP client.")
                    client.close()
                    log("HTTP client closed.")
                }
                return@async 1
            }
        }
        for(i in 0 until tasks.size){
            sum += tasks[i].await()
            log("Task #${i} completed.")
        }
        return sum
    }

    private fun log(message: String){
        println("[${Thread.currentThread().name}] ${message}")
    }
}

In particular, testWithGlobalScope (Apache HTTP, called from GlobalScope.async(...)) tends to freeze almost every try at some point (although I observed that the target web URL does make a difference; perhaps it’s a race condition dependent on the response time?). The other two variants work fine for me.

As a side note, I have observed that if you are in a test run where the HTTP client causes a freeze, it will always occur after the n-th request, where n is the number of CPU cores on your machine (I guess that kotlin determines the size of its executor pools based on this number, when the pools run out of usable threads the remaining coroutines can’t execute anymore).

Interestingly, if we replace HttpClient(Apache) by HttpClient(CIO), then things work like a charm. I would argue that this strongly points towards the Apache HTTP Client as the culprit of the deadlocks.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
MartinHaeuslercommented, Feb 27, 2019

Oh okay… well, I’m glad to see this issue fixed, thanks for the explanation 😃 👍

1reaction
e5lcommented, Feb 14, 2019

Thanks for the report, I’ll investigate and report the details.

Read more comments on GitHub >

github_iconTop Results From Across the Web

HttpClient hangs when doing a second request - Stack Overflow
I was reading somewhere that this way of HttpClient closes itself. And the DefaultHttpClient has been deprecated. java · apache · httpclient ......
Read more >
Understanding Async, Avoiding Deadlocks in C# | by Eke Péter
Sync version, blocks the thread, not safe: · Calling HttpClient. · This is where it will create a Task and return it in...
Read more >
You're using HttpClient wrong and it is destabilizing your ...
Once the using block is complete then the disposable object, in this case HttpClient , goes out of scope and is disposed.
Read more >
Don't Block the Event Loop (or the Worker Pool) - Node.js
While a thread is blocked working on behalf of one client, it cannot handle requests from any other clients. This provides two motivations...
Read more >
Fix List for Db2 Version 11.1 for Linux, UNIX and Windows - IBM
APAR Sev. Abstract IT36427 2 MON_GET_AUTO_MAINT_QUEUE() MAY FAIL WITH SQL0493N IT37394 3 DB2PD ‑BUFFERPOOLS REPORTS INACCURATE HIT RATIO IT36689 2 REORGCHK F6 REPORTING INCORRECT VALUES
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found