Skip to content

Conversation

@Antamansid
Copy link
Collaborator

@Antamansid Antamansid commented Sep 8, 2025

Race condition in scheduler iteration

The performUpdate() method iterates through scheduler arrays while scheduler callbacks can call removeScheduler(), which modifies the arrays in-place using splice(). This causes iteration to skip elements when a scheduler is removed during the loop:
Loop at index j=1, processing scheduler B
Scheduler B calls removeScheduler() for themself at index 1
Array shifts: [A,B,C,D] → [A,C,D], so C moves from index 2 to index 1
Loop increments to j=2, skipping scheduler C entirely
Fixed by implementing deferred removal - schedulers are marked for deletion during iteration and actually removed before the next update cycle.

@Antamansid Antamansid requested a review from draedful as a code owner September 8, 2025 06:17
@gravity-ui-bot
Copy link
Contributor

Preview is ready.

fn(...latestArgs);
if (removeScheduler) {
removeScheduler();
removeScheduler = null;
Copy link
Collaborator Author

@Antamansid Antamansid Sep 8, 2025

Choose a reason for hiding this comment

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

I admit, I spent a lot of time trying to figure out why sometimes it doesn't work.
If you try to install console.log() in hitTest debounce, you will see that it is not deleted from the GlobalScheduler, but is spinning endlessly. Perhaps this is a problem due to StrictMode and the fact that when the Graph is recreated, GlobalScheduler is not recreated.
The current fix with a queue for deletion, if anything, does not solve the problem.

All in all, there is no need to equate to null, since during iteration there is a check for the presence of an element in the array.

@Antamansid Antamansid merged commit 48d5022 into main Sep 11, 2025
6 checks passed
@Antamansid Antamansid deleted the scheduler_fix branch September 11, 2025 14:31
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.

4 participants