Skip to content

Ktor Curl engine hangs/freezes after multiple requests on Linux x64 (Kotlin Native) #5222

@orchestr7

Description

@orchestr7

Environment

  • Ktor version: 3.3.2
  • Kotlin version: 2.2.21
  • Platform: Linux x64 (Kotlin Native)
  • Engine: Curl
  • OS: Linux
  • FROM --platform=linux/amd64 alpine:latest
    RUN apk add --no-cache gcompat libcurl libgcc libstdc++

Description

The Ktor Curl engine appears to have a resource leak or connection pool issue that causes requests to hang indefinitely after a certain number of requests (typically around 80-100 requests in my testing). This happens flaky and causes serious issues while connecting to paginated pages.

Reproduction Steps

  1. Create a Kotlin Multiplatform project targeting linuxX64()
  2. Use the Curl engine with timeout and retry configurations
  3. Make repeated HTTP requests in a loop
  4. Observe that after ~80-100 requests, the application hangs

Complete Minimal Reproduction

Click to expand full code
// build.gradle.kts
val ktorVersion: String = "3.3.2"

plugins {
    kotlin("multiplatform") version "2.2.21"
    kotlin("plugin.serialization") version "2.2.21"
}

repositories {
    mavenCentral()
}

kotlin {
    linuxX64().apply {
        binaries {
            executable {
                entryPoint = "test.main"
            }
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-core:$ktorVersion")
                implementation("io.ktor:ktor-client-curl:$ktorVersion")
            }
        }
    }
}
// Main.kt
package test

import io.ktor.client.*
import io.ktor.client.engine.curl.Curl
import io.ktor.client.plugins.HttpTimeout
import io.ktor.client.request.*
import io.ktor.client.statement.*
import kotlinx.coroutines.*

fun main() = runBlocking {
    val client = HttpClient(Curl) {
        install(HttpTimeout) {
            requestTimeoutMillis = 10000
            connectTimeoutMillis = 5000
            socketTimeoutMillis = 6000
        }
    }

    var pageCount = 0
    while(true) {
        pageCount++
        println("Page $pageCount")
        
        try {
            val result = withTimeoutOrNull(20000) {
                val response = client.get("https://google.com")
                response.bodyAsText()
            }
            
            if (result == null) {
                println("REQUEST TIMED OUT - HANGING DETECTED")
                break
            }
        } catch (e: Exception) {
            println("Exception: ${e.message}")
            break
        }
    }
    
    client.close()
}

Logs

The application runs successfully for multiple requests, then hangs:

Page 1
Page 2
Page 3
Page 4
Page 5
Page 6
Page 7
Page 8
Page 9
Page 10
Page 11
Page 12
Page 13
Page 14
Page 15
Page 16
Page 17
<FREEZE>

Analysis

  1. Consistent failure point: The hang occurs consistently , but randomly. Everything works on MAC.
  2. Timeout ignored: The configured HTTP timeouts (5s/6s/10s) and even the coroutine timeout (20s) are not respected
  3. Platform specific: This issue appears specific to the Curl engine on Linux x64. Everything works on MAC.

Potential Root Causes

  • Connection pool not properly releasing connections?
  • File descriptor leak in the native Curl integration?
  • Memory leak in the Kotlin Native <-> libcurl bridge?
  • Some problem with retry mechanism?

Additional Information

This issue makes the Curl engine unreliable for long-running applications or applications that need to make many HTTP requests. The problem appears to be at the native layer since Kotlin/JVM timeouts are not respected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions