From b68907353f5c48c56dd8b557025f02caa9f0de87 Mon Sep 17 00:00:00 2001 From: wuyangfan Date: Mon, 25 May 2026 11:06:42 +0800 Subject: [PATCH] Clarify Dispatcher executor sizing requirements in KDoc The previous wording implied that an executor sized to maxRequests is sufficient. In practice, promoteAndExecute() submits the next call from a worker thread before it returns to the queue, which can cause RejectedExecutionException with SynchronousQueue and a fixed-size pool. Fixes #9443 Co-authored-by: Cursor --- .../src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt index 02f58f1fc807..54b7cd1069d3 100644 --- a/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt +++ b/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt @@ -31,8 +31,14 @@ import okhttp3.internal.unmodifiable * Policy on when async requests are executed. * * Each dispatcher uses an [ExecutorService] to run calls internally. If you supply your own - * executor, it should be able to run [the configured maximum][maxRequests] number of calls - * concurrently. + * executor, it must accept any new task at any time while up to [the configured maximum][maxRequests] + * calls are already running. A pool sized exactly to `maxRequests` is not sufficient when paired + * with [SynchronousQueue], because the dispatcher submits the next promoted call from a worker + * thread that has not yet returned to the queue; the offer will fail and the call will surface + * [InterruptedIOException] with message `"executor rejected"`. + * + * Match the pattern used by the default executor (`corePoolSize=0`, `maxPoolSize=Int.MAX_VALUE`, + * [SynchronousQueue]), bound the maximum at `2 × maxRequests`, or use a queueing executor. */ class Dispatcher() { /**