Skip to content

fix: prevent suspend/resume event buffer infinite loop#306

Open
YunchuWang wants to merge 1 commit into
microsoft:mainfrom
YunchuWang:copilot-finds/bug/fix-suspend-resume-infinite-loop
Open

fix: prevent suspend/resume event buffer infinite loop#306
YunchuWang wants to merge 1 commit into
microsoft:mainfrom
YunchuWang:copilot-finds/bug/fix-suspend-resume-infinite-loop

Conversation

@YunchuWang

Copy link
Copy Markdown
Member

Summary

  • Snapshot and clear suspended events before replaying them.
  • Keep newly buffered events for the next resume cycle and avoid buffering suspend events.
  • Add regression coverage for resumed event processing.

Fixes #202

Testing

  • npm test -w @microsoft/durabletask-js -- --runTestsByPath test/orchestration_executor.spec.ts
  • npm run build:core

handleExecutionResumed iterates _suspendedEvents using for..of while
processEvent can push new entries onto the same array. If a buffered
ExecutionSuspended event sets _isSuspended=true during iteration,
subsequent suspendable events are re-pushed to the array being
iterated, creating an infinite loop that hangs the worker process.

Two fixes:

1. Snapshot _suspendedEvents before iterating and clear it first.
   Events buffered during processing land in the new (empty) array
   and are correctly held for the next Resume event.

2. Add ExecutionSuspended to the isSuspendable exclusion list so
   suspend events are processed immediately rather than buffered.
   Also uses strict equality (===) instead of loose (==) for the
   indexOf check.

Co-authored-by: Copilot <[email protected]>
Copilot AI review requested due to automatic review settings July 17, 2026 16:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes a worker hang in the Durable Task JS orchestration executor by preventing re-entrant modification of the suspended event buffer during resume processing, and adds regression tests to ensure suspend/resume buffering remains safe.

Changes:

  • Snapshot-and-clear _suspendedEvents before replaying buffered events on ExecutionResumed to prevent an infinite loop.
  • Treat ExecutionSuspended as non-suspendable (never buffered) and tighten the suspendable check to strict equality.
  • Add regression tests covering buffered events that include an extra suspend and ensuring ExecutionSuspended is never buffered.

Reviewed changes

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

File Description
packages/durabletask-js/src/worker/orchestration-executor.ts Snapshots/clears suspended event buffer before iterating to avoid infinite loop on resume.
packages/durabletask-js/src/worker/index.ts Updates isSuspendable to exclude ExecutionSuspended and use strict equality.
packages/durabletask-js/test/orchestration_executor.spec.ts Adds regression tests for suspend/resume buffering edge cases and infinite-loop prevention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[copilot-finds] Bug: handleExecutionResumed iterates _suspendedEvents while modifying it, causing infinite loop

3 participants