-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
BlockHound false positive in WorkQueue.addLast #2937
Comments
Thanks for the report, this is really a false positive and will be fixed, but could you please describe how you managed to trigger this? |
It was a once-only result from a bigger data-driven stress test suite, which typically run several times a week. I have never seen this one before (and have added a BlockHound exception thereafter), so it seems like a rare race condition as indicated by the comment in Unfortunately, the code is not for publication and there are many moving parts involved, but I'll try: I am collecting updates from a flow. Each collection is guarded by a per-collection timeout. This is achieved by launching a timeout job before each collection, which will cancel the collection if it times out, otherwise it is cancelled and restarted. Depending on the test scenario, there can be up to 1000 concurrent collector jobs (via Dispatchers.Default), each collecting up to 1000 updates (which also means 1000 collectors each starting a timeout job 1000 times). I suspect the full stack trace below is not completely accurate since there is no Here is a (slightly simplified) excerpt: class MonitoredSubscription(private val id: Int) : Subscription() {
// properties omitted
private fun CoroutineScope.timeoutJob(
collectorJob: Job,
timeout: Duration,
expectCancellation: Boolean = false
) = launch {
delay(timeout)
if (!expectCancellation)
logger.error { "Cancelling collector for ${this@MonitoredSubscription} after $timeout" }
collectorJob.cancel(CancellationException("collect timed out after $timeout"))
}
fun collectUpdates(scope: CoroutineScope, updateGroupID: String, expectUpdates: Boolean) {
val timeout = if (expectUpdates) Duration.seconds(2) else Duration.milliseconds(100)
scope.launch {
withDebugLogging(logger, prefix = "collecting changes via ${this@MonitoredSubscription}") {
val collectorJob = coroutineContext.job
var timeoutJob = timeoutJob(collectorJob, timeout, !expectUpdates)
updates().collect { update -> // <-- at vc.backendCache.SubscriptionStressTest$MonitoredSubscription.collectUpdates(SubscriptionStressTest.kt:89)
timeoutJob.cancel()
// processing omitted
if (collectedTargets.size == subscribedTargets.size)
cancel()
timeoutJob = timeoutJob(collectorJob, timeout, !expectUpdates)
}
timeoutJob.cancel()
}
}
}
} This is the full stack trace:
Does that help? |
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1
Relevant stack trace excerpt:
The text was updated successfully, but these errors were encountered: