TimurRakhmatullin86 opened a new pull request, #20424: URL: https://github.com/apache/druid/pull/20424
## Summary Restore the thread interrupt flag in `catch (InterruptedException)` blocks that swallow the exception without calling `Thread.currentThread().interrupt()`. This is a well-documented Java concurrency best practice (see *Java Concurrency in Practice*, Section 7.1.3). When `InterruptedException` is caught and not re-thrown, the thread's interrupt status is cleared. If the catch block does not restore it, higher-level code (thread pool executors, shutdown hooks, cooperative cancellation loops) cannot detect that an interruption was requested. This can cause threads to miss shutdown signals and continue running indefinitely. ### Notable fixes **`CommonCacheNotifier`** — The catch block inside a `while (!Thread.interrupted())` loop swallowed the interrupt, preventing the loop from ever terminating on shutdown. After `exec.shutdownNow()`, the thread would catch the `InterruptedException` from `updateQueue.take()`, lose the flag, and re-enter the loop — blocking on `take()` indefinitely. **`HttpPostEmitter`** — The `EmittingThread` run loop checks `Thread.interrupted()` in its `needsToShutdown()` method. The `sendWithRetries()` method caught `InterruptedException` without restoring the flag, so the emitting thread could miss its shutdown signal. ### All changes (12 files, 18 catch blocks) | Module | File | Description | |--------|------|-------------| | `extensions-core/druid-basic-security` | `CommonCacheNotifier` | Restore flag so `while (!Thread.interrupted())` loop can exit | | `extensions-core/druid-basic-security` | `CoordinatorPollingBasicAuthorizerCacheManager` | Restore flag in 4 catch blocks (scheduled poll tasks + fetch methods) | | `extensions-core/druid-basic-security` | `CoordinatorPollingBasicAuthenticatorCacheManager` | Restore flag in 2 catch blocks (scheduled poll task + fetch method) | | `extensions-core/kinesis-indexing-service` | `KinesisRecordSupplier` | Restore flag in `poll()` | | `extensions-core/kafka-extraction-namespace` | `KafkaLookupExtractorFactory` | Restore flag in multi-catch during `start()` | | `extensions-core/kubernetes-overlord-extensions` | `KubernetesPeonLifecycle` | Restore flag in `executeWithTimeout()` | | `extensions-contrib/rabbit-stream-indexing-service` | `RabbitStreamRecordSupplier` | Restore flag in 3 catch blocks (`close()`, message handler, `poll()`) | | `multi-stage-query` | `WorkerSketchFetcher` | Restore flag before `executorService.shutdownNow()` | | `processing` | `HttpPostEmitter` | Restore flag so `EmittingThread.needsToShutdown()` sees the interrupt | | `server` | `DirectDruidClient` | Restore flag in multi-catch during query cancellation | | `server` | `LookupReferencesManager` | Restore flag in multi-catch during lookup loading | | `server` | `LookupCoordinatorManager` | Restore flag in executor-submitted callable | ### Motivation All changes follow the same minimal pattern — adding `Thread.currentThread().interrupt()` as the first statement in the catch block. No behavioral logic is changed; this purely restores the interrupt flag that `InterruptedException` clears, so that callers can observe it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
