Eric Chang created KAFKA-20802:
----------------------------------

             Summary: ClusterTestExtensions#afterEach throws NPE when a 
detected thread terminates before the leak report is built
                 Key: KAFKA-20802
                 URL: https://issues.apache.org/jira/browse/KAFKA-20802
             Project: Kafka
          Issue Type: Bug
            Reporter: Eric Chang
            Assignee: Eric Chang


{{ClusterTestExtensions#afterEach}} builds the thread-leak error message with 
{{t.getThreadGroup().getName()}}. {{Thread#getThreadGroup()}} returns null 
after a thread has terminated.

If a thread returned by {{DetectThreadLeak#newThreads()}} terminates between 
the snapshot and message formatting, {{afterEach}} throws an NPE and fails the 
test even though the thread is no longer a leak.

h3. CI evidence

* Full job: 
https://github.com/apache/kafka/actions/runs/29228499012/job/86748625389
* NPE in the JUnit test step: 
https://github.com/apache/kafka/actions/runs/29228499012/job/86748625389#step:6:136310
* Flaky-test report: 
https://github.com/apache/kafka/actions/runs/29228499012/job/86748625389#step:10:1872
* Affected test: {{MetadataQuorumCommandTest.testDescribeQuorumStatusSuccessful 
[5]}}

{code}
java.lang.NullPointerException: Cannot invoke "java.lang.ThreadGroup.getName()" 
because the return value of "java.lang.Thread.getThreadGroup()" is null
    at 
org.apache.kafka.common.test.junit.ClusterTestExtensions.lambda$afterEach$2(ClusterTestExtensions.java:188)
{code}

h3. Reproduction

A deterministic regression test can reproduce the same NPE by making 
{{DetectThreadLeak#newThreads()}} return a thread that has already been joined, 
then invoking the real {{afterEach}} path. The proposed logic passes this 
regression test and continues to report live leaked threads.

I also ran the actual affected test locally for 120 isolated cluster contexts 
using Java 17, 4 forks, and retries disabled. All 120 passed, so the natural 
timing window did not reproduce locally in that batch.

h3. Expected behavior

Threads that have already terminated should be ignored while constructing the 
leak report because they are not leaks. The reporting path must not throw an 
NPE.

h3. Related issue

KAFKA-17189 (https://issues.apache.org/jira/browse/KAFKA-17189) describes the 
underlying snapshot-to-report race and proposes adding {{Thread::isAlive}} to 
the leak-detector filter. This issue tracks the concrete 
{{ClusterTestExtensions#afterEach}} NPE observed in CI.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to