Skip to content

Fix NPE in HelixTaskExecutor.reset() when a task completes during shutdown - #3168

Open
Jackie-Jiang wants to merge 1 commit into
apache:masterfrom
Jackie-Jiang:fix-task-executor-reset-npe
Open

Fix NPE in HelixTaskExecutor.reset() when a task completes during shutdown#3168
Jackie-Jiang wants to merge 1 commit into
apache:masterfrom
Jackie-Jiang:fix-task-executor-reset-npe

Conversation

@Jackie-Jiang

Copy link
Copy Markdown

Issues

  • My PR addresses the following Helix issues and references them in the PR description:

Fixes #3167

Description

  • Here are some details about my PR, including screenshots of any UI changes:

HelixTaskExecutor.reset() ends with a loop that logs tasks failing to terminate by iterating _taskMap.keySet() and then calling get(taskId). _taskMap is a ConcurrentHashMap and message tasks remove themselves from it when they finish, so a task completing while reset() runs disappears between the two calls: get returns null and reading info._task throws

java.lang.NullPointerException: Cannot read field "_task" because "info" is null

which propagates out of reset() and can fail the participant disconnect (observed intermittently in Apache Pinot integration-test teardowns).

This change iterates entrySet() instead: each entry is read atomically, so a concurrently-completing task is either logged or skipped, but can never yield a null value. No behavior change for tasks genuinely still present.

Tests

  • The following tests are written for this issue:

None — the fix removes a data race in a shutdown logging loop; the race window (concurrent task completion between two map reads inside reset()) is not deterministically reproducible from a unit test without intrusive instrumentation.

Commits

  • My commits all reference appropriate Apache Helix GitHub issues in their subject lines and follow the commit message guidelines.

Code Quality

  • My diff has been formatted using helix-style.xml

The final logging loop in reset() iterated _taskMap.keySet() and then
called get(taskId) on the ConcurrentHashMap. A message task completing
concurrently removes itself from the map between the two calls, so get
returns null and reading info._task throws, failing the participant
disconnect. Iterating entrySet() reads each entry atomically, so a
concurrently-completing task is either logged or skipped, never null.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NPE in HelixTaskExecutor.reset() when a task completes during shutdown

1 participant