Repository navigation
Avoid the Netty global executor race in instrumentation tests - #13050
Draft
AlexeyKuznetsov-DD wants to merge 1 commit into
Draft
AlexeyKuznetsov-DD wants to merge 1 commit into
AlexeyKuznetsov-DD wants to merge 1 commit into
Conversation
[ci: ARM64, NON_DEFAULT_JVMS]
Contributor
🟡 Java Benchmark SLOs — Performance SLO warning (near threshold)
PR vs. master results
Commit: Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What Does This Do
netty-concurrent-4.0test baseline, with the corresponding lockfile update.Production compilation and muzzle compatibility still start at 4.0.0.Final. Scope and continuation checks remain enabled.
Motivation
An ARM64 Java 27 test run exhausted the 20-minute task deadline while closing an executor group in
testDelayedScheduledFutureTaskActivatesCapturedContinuationWhenDelayExpires. The child executor had already terminated; its parent group never received the termination notification.This matches the upstream
GlobalEventExecutorrace addressed by Netty commit 28b8573 — Fix a potential race condition where the worker thread of GlobalEventExecutor terminates with a pending task, dated July 18, 2013. 4.0.4.Final is the first 4.0 patch release containing that commit (absent from the 4.0.3.Final tag, present in 4.0.4.Final).The original submission order checks/starts the worker before enqueueing the task. An existing worker can exit between those operations, leaving the notification queued with nobody to execute it. The upstream change enqueues first, then checks/starts the worker.
sequenceDiagram autonumber participant C as Child executor participant Q as Notification queue participant W as Global worker participant G as Executor group participant T as Test worker rect rgb(255, 235, 238) Note over C,T: BEFORE · Netty 4.0.0.Final · lost termination notification C->>W: startThread() observes an existing worker W->>Q: Check for pending tasks Q-->>W: Empty W->>W: Exit and reset state to NOT_STARTED C->>Q: addTask(child termination listener) Note over Q,W: Heap: 1 queued task, worker already terminated T->>G: Wait for group termination Note over G,T: Heap: terminatedChildren = 0 / 1<br/>Group promise remains pending end rect rgb(232, 245, 233) Note over C,T: AFTER · Netty 4.0.4.Final · enqueue before starting C->>Q: addTask(child termination listener) C->>W: startThread() starts a worker if needed W->>Q: Poll pending task Q-->>W: Child termination listener W->>G: Notify child termination G-->>T: Complete group termination promise Note over G,T: Cleanup completes<br/>A separate 5-second guard reports future regressions endAdditional Notes
Thread and heap evidence
The matching thread dump showed the test worker waiting in cleanup:
The heap captured during the stall identifies the missing notification:
TERMINATEDterminatedChildren = 0,children.length = 1; termination promise unresolvedNOT_STARTED; previous worker thread terminated; one task queuedPromiseTask → RunnableAdapter → DefaultPromise$3, referencing that child's termination promise and the parent'sMultithreadEventExecutorGroup$1listenerThe object references connect the queued callback to the exact child and parent involved in the blocked cleanup. This is a notification-dispatch failure. The evidence does not implicate slow class retransformation or establish an incorrect continuation ownership transition.
Agent-free reproduction
A temporary standalone Java 17 reproducer controlled the interleaving at the enqueue boundary: hold submission immediately before queue insertion, let the previous global worker terminate, then release submission. It loaded Netty without the Datadog agent and asserted the expected result for each version:
The reproducer uses reflective queue replacement to make the race deterministic and is not included in the repository. The production test change adopts the upstream correction and adds a bounded cleanup assertion. A single successful run against the original version would not exclude this intermittent race.
Validation
The module's
allTeststask completed on local ARM64 Java 8 and Java 27. It coverstest,forkedTest,executorTest,legacyNettyTest,legacyNettyTestForkedTest,netty4144Test, andnetty4144TestForkedTest(latest-dependency suites are excluded by the task's normal convention).The affected nine-case scheduled-future test class also passed separately on Java 27. ARM64 CI confirmation is pending.
The change is confined to test dependencies and test cleanup; it adds no tracer runtime work.
Contributor Checklist
type:and (comp:orinst:) labels in addition to any other useful labelsclose,fix, or any linking keywords when referencing an issueUse
solvesinstead, and assign the PR milestone to the issue