Skip to content

fix(net): fix RejectedExecutionException during shutdown trxHandlePool#8

Open
0xbigapple wants to merge 1 commit intodevelopfrom
fix/threadpool-submit-issue
Open

fix(net): fix RejectedExecutionException during shutdown trxHandlePool#8
0xbigapple wants to merge 1 commit intodevelopfrom
fix/threadpool-submit-issue

Conversation

@0xbigapple
Copy link
Copy Markdown
Owner

@0xbigapple 0xbigapple commented Mar 30, 2026

What does this PR do?
fix RejectedExecutionException during shutdown trxHandlePool

Why are these changes required?

This PR has been tested by:

  • Unit Tests
  • Manual Testing

Follow up

Extra details


Summary by cubic

Fixes RejectedExecutionException during shutdown by blocking new submissions, shutting down the scheduler before the worker pool, and clearing queues. Ensures clean shutdown after close, ignores new messages, and drops only queued smart‑contract tasks.

  • Bug Fixes
    • Gate submissions with volatile isClosed; early return in processMessage and re-check during batch.
    • Shutdown order: stop smartContractExecutor first, then trxHandlePool; clear smartContractQueue and internal queue.
    • Wrap submits to trxHandlePool in try/catch RejectedExecutionException; stop submitting on first rejection.
    • Tests: ignore messages after close; handleTransaction broadcasts valid tx; on BAD_TRX, mark peer bad and disconnect with BAD_TX.

Written for commit b530d30. Summary will update on new commits.

Summary by CodeRabbit

  • Refactor

    • Improved transaction processing stability with enhanced shutdown handling and better error recovery when system resources are constrained, reducing potential disruptions during peak activity periods.
  • Tests

    • Added test coverage for shutdown scenarios and transaction processing workflows to ensure reliability.

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

📝 Walkthrough

Walkthrough

Added graceful shutdown mechanism to TransactionsMsgHandler by introducing a closed state flag that gates message processing and task submission, with ordered executor shutdown and exception handling for rejected executions. Accompanying tests verify closed-state behavior and transaction handling with mocked dependencies.

Changes

Cohort / File(s) Summary
Shutdown State Management
framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java
Introduced isClosed flag to track handler lifecycle. Modified close() to shut down smart-contract scheduler first, then transaction worker pool, and clear associated queues. Updated processMessage() to drop messages when closed and handle RejectedExecutionException during task submission with warning log and loop break.
Lifecycle and Exception Handling Tests
framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java
Added testProcessMessageAfterClose to verify messages are dropped after handler closure. Added testHandleTransaction using reflection to test private method behavior with mocked delegates, including peer disconnection on BAD_TRX exceptions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A bundle of thorns now smoothly won't prick,
For shutdown's sequential, orderly, quick—
State flags guard the gates, exceptions are caught,
And tasks bow gracefully, as they ought!
Tested and true, this handler's robust,
In robust design, we place our trust. 🐇

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and clearly summarizes the main change: fixing RejectedExecutionException that occurs during trxHandlePool shutdown.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/threadpool-submit-issue

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes shutdown-time RejectedExecutionException in TransactionsMsgHandler by preventing new task submissions after close and changing executor shutdown ordering to stop the scheduler before the worker pool.

Changes:

  • Add an isClosed flag and guard processMessage/iteration to stop submitting work during shutdown.
  • Change shutdown order to terminate smartContractExecutor before trxHandlePool, and catch RejectedExecutionException on submit.
  • Add a unit test to ensure processMessage() does not throw after close().

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java Adds close-gating and adjusts executor shutdown order to avoid rejected submissions during shutdown.
framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java Adds a regression test ensuring processMessage is safe after handler close.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +97 to +101
// Re-check isClosed status during iteration to handle concurrent shutdown
if (isClosed) {
logger.warn("TransactionsMsgHandler is closed during processing, stop submit.");
break;
}
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When isClosed flips to true (or trxHandlePool starts rejecting), this loop breaks early, but the earlier loop has already removed all tx items from peer.getAdvInvRequest(). That can leave some transactions neither queued nor requested anymore. To avoid silently dropping txs, consider removing items from advInvRequest only after a tx is successfully enqueued/submitted (or stop removing once shutdown is detected).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@0xbigapple 0xbigapple force-pushed the fix/threadpool-submit-issue branch from 4d5d454 to 595f6a8 Compare April 16, 2026 11:32
@0xbigapple
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java (1)

154-206: Add cleanup to avoid leaking executor threads.

The test creates a TransactionsMsgHandler whose field initializers instantiate real thread pools (trxHandlePool and smartContractExecutor). Without calling close(), these executors remain running after the test completes, potentially causing resource leaks or test pollution.

🧹 Proposed fix to add cleanup
 `@Test`
 public void testHandleTransaction() throws Exception {
   TransactionsMsgHandler handler = new TransactionsMsgHandler();
+  try {
     TronNetDelegate tronNetDelegate = Mockito.mock(TronNetDelegate.class);
     // ... existing test code ...
     Mockito.verify(peer).setBadPeer(true);
     Mockito.verify(peer).disconnect(Protocol.ReasonCode.BAD_TX);
+  } finally {
+    handler.close();
+  }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java`
around lines 154 - 206, The test leaks executor threads because
TransactionsMsgHandler's field initializers create real thread pools
(trxHandlePool and smartContractExecutor) that are not shut down; fix by
ensuring these are closed after the test—either call handler.close() (or if no
public close exists, reflectively get and shutdown the trxHandlePool and
smartContractExecutor fields) in a finally block at the end of
testHandleTransaction or move cleanup into an `@After` method to always shut down
those executors; reference TransactionsMsgHandler, trxHandlePool,
smartContractExecutor, and close()/shutdown() when applying the change.
framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java (1)

136-151: Consider adding try/catch for consistency (optional).

While the shutdown order guarantees trxHandlePool is still running when this method executes, adding a try/catch for RejectedExecutionException would make the code more defensive and consistent with processMessage().

🔧 Optional defensive improvement
 private void handleSmartContract() {
   ExecutorServiceManager.scheduleWithFixedDelay(smartContractExecutor, () -> {
     try {
       while (queue.size() < MAX_SMART_CONTRACT_SUBMIT_SIZE && smartContractQueue.size() > 0) {
         TrxEvent event = smartContractQueue.take();
-        ExecutorServiceManager.submit(
-            trxHandlePool, () -> handleTransaction(event.getPeer(), event.getMsg()));
+        try {
+          ExecutorServiceManager.submit(
+              trxHandlePool, () -> handleTransaction(event.getPeer(), event.getMsg()));
+        } catch (RejectedExecutionException e) {
+          logger.warn("Submit task to {} failed during shutdown", trxEsName);
+          break;
+        }
       }
     } catch (InterruptedException e) {
       logger.warn("Handle smart server interrupted");
       Thread.currentThread().interrupt();
     } catch (Exception e) {
       logger.error("Handle smart contract exception", e);
     }
   }, 1000, 20, TimeUnit.MILLISECONDS);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java`
around lines 136 - 151, The scheduled task in handleSmartContract submits jobs
to trxHandlePool without guarding for RejectedExecutionException; wrap the
ExecutorServiceManager.submit(trxHandlePool, () ->
handleTransaction(event.getPeer(), event.getMsg())) call in its own try/catch
that catches RejectedExecutionException and logs a warning (including
identifying info such as event.getPeer() or event) so the failure is visible and
the loop can continue; keep existing InterruptedException and generic Exception
handlers as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java`:
- Around line 136-151: The scheduled task in handleSmartContract submits jobs to
trxHandlePool without guarding for RejectedExecutionException; wrap the
ExecutorServiceManager.submit(trxHandlePool, () ->
handleTransaction(event.getPeer(), event.getMsg())) call in its own try/catch
that catches RejectedExecutionException and logs a warning (including
identifying info such as event.getPeer() or event) so the failure is visible and
the loop can continue; keep existing InterruptedException and generic Exception
handlers as-is.

In
`@framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java`:
- Around line 154-206: The test leaks executor threads because
TransactionsMsgHandler's field initializers create real thread pools
(trxHandlePool and smartContractExecutor) that are not shut down; fix by
ensuring these are closed after the test—either call handler.close() (or if no
public close exists, reflectively get and shutdown the trxHandlePool and
smartContractExecutor fields) in a finally block at the end of
testHandleTransaction or move cleanup into an `@After` method to always shut down
those executors; reference TransactionsMsgHandler, trxHandlePool,
smartContractExecutor, and close()/shutdown() when applying the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a71c64cd-51ca-44f4-921c-93b3f371bb29

📥 Commits

Reviewing files that changed from the base of the PR and between 208807d and 595f6a8.

📒 Files selected for processing (2)
  • framework/src/main/java/org/tron/core/net/messagehandler/TransactionsMsgHandler.java
  • framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java

@0xbigapple 0xbigapple force-pushed the fix/threadpool-submit-issue branch from 595f6a8 to b530d30 Compare April 16, 2026 12:08
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.

2 participants