Skip to content

[SPARK-59714][CORE] Align TaskSchedulerImpl.executorDecommission locking with executorLost - #58970

Closed
dongjoon-hyun wants to merge 1 commit into
apache:masterfrom
dongjoon-hyun:SPARK-59714
Closed

dongjoon-hyun wants to merge 1 commit into
apache:masterfrom
dongjoon-hyun:SPARK-59714

Conversation

@dongjoon-hyun

Copy link
Copy Markdown
Member

What changes were proposed in this pull request?

This PR moves rootPool.executorDecommission(executorId) inside the synchronized block that
TaskSchedulerImpl.executorDecommission() already has, keeping backend.reviveOffers() outside it.

Why are the changes needed?

rootPool.executorDecommission() reaches TaskSetManager.recomputeLocality(), and
TaskSchedulerImpl documents that "TaskSetManagers are not thread safe, so any access to one should
be synchronized on this class". The sibling executorLost() path already follows this: it calls
rootPool.executorLost() inside the lock and keeps only the dagScheduler and backend calls
outside. This makes the two paths consistent.

There is no behavior change. The only production caller,
CoarseGrainedSchedulerBackend.decommissionExecutors(), is withLock, which already holds this
same monitor, so the call was effectively synchronized in practice. This PR makes the method
self-contained instead of relying on its caller.

Does this PR introduce any user-facing change?

No.

How was this patch tested?

Pass the CIs.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Opus 5

@dongjoon-hyun

dongjoon-hyun commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

Could you review this code-path improvement PR (about executorDecommission) when you have some time, @peter-toth ?

@dongjoon-hyun

Copy link
Copy Markdown
Member Author

Thank you so much, @peter-toth !

dongjoon-hyun added a commit that referenced this pull request Sep 22, 2026
…cking with `executorLost`

### What changes were proposed in this pull request?

This PR moves `rootPool.executorDecommission(executorId)` inside the `synchronized` block that
`TaskSchedulerImpl.executorDecommission()` already has, keeping `backend.reviveOffers()` outside it.

### Why are the changes needed?

`rootPool.executorDecommission()` reaches `TaskSetManager.recomputeLocality()`, and
`TaskSchedulerImpl` documents that "TaskSetManagers are not thread safe, so any access to one should
be synchronized on this class". The sibling `executorLost()` path already follows this: it calls
`rootPool.executorLost()` inside the lock and keeps only the `dagScheduler` and `backend` calls
outside. This makes the two paths consistent.

There is no behavior change. The only production caller,
`CoarseGrainedSchedulerBackend.decommissionExecutors()`, is `withLock`, which already holds this
same monitor, so the call was effectively synchronized in practice. This PR makes the method
self-contained instead of relying on its caller.

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

Pass the CIs.

### Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Opus 5

Closes #58970 from dongjoon-hyun/SPARK-59714.

Authored-by: Dongjoon Hyun <dongjoon@apache.org>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
(cherry picked from commit 582e28b)
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
dongjoon-hyun added a commit that referenced this pull request Sep 22, 2026
…cking with `executorLost`

### What changes were proposed in this pull request?

This PR moves `rootPool.executorDecommission(executorId)` inside the `synchronized` block that
`TaskSchedulerImpl.executorDecommission()` already has, keeping `backend.reviveOffers()` outside it.

### Why are the changes needed?

`rootPool.executorDecommission()` reaches `TaskSetManager.recomputeLocality()`, and
`TaskSchedulerImpl` documents that "TaskSetManagers are not thread safe, so any access to one should
be synchronized on this class". The sibling `executorLost()` path already follows this: it calls
`rootPool.executorLost()` inside the lock and keeps only the `dagScheduler` and `backend` calls
outside. This makes the two paths consistent.

There is no behavior change. The only production caller,
`CoarseGrainedSchedulerBackend.decommissionExecutors()`, is `withLock`, which already holds this
same monitor, so the call was effectively synchronized in practice. This PR makes the method
self-contained instead of relying on its caller.

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

Pass the CIs.

### Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Opus 5

Closes #58970 from dongjoon-hyun/SPARK-59714.

Authored-by: Dongjoon Hyun <dongjoon@apache.org>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
(cherry picked from commit 582e28b)
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
@dongjoon-hyun

Copy link
Copy Markdown
Member Author

Merge Summary:

Posted by merge_spark_pr.py

@dongjoon-hyun
dongjoon-hyun deleted the SPARK-59714 branch September 22, 2026 19:17
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