Skip to content

Fix hanging process when participant disconnects during init#1087

Open
lukasIO wants to merge 4 commits intomainfrom
lukas/hang-fixes
Open

Fix hanging process when participant disconnects during init#1087
lukasIO wants to merge 4 commits intomainfrom
lukas/hang-fixes

Conversation

@lukasIO
Copy link
Contributor

@lukasIO lukasIO commented Mar 2, 2026

Description

closes #927
when func(ctx) throws, the entire cleanup path is skipped because there was no try-catch around it. The joinFuture is never resolved, so the process never exits.

Changes Made

Pre-Review Checklist

  • Build passes: All builds (lint, typecheck, tests) pass locally
  • AI-generated code reviewed: Removed unnecessary comments and ensured code quality
  • Changes explained: All changes are properly documented and justified above
  • Scope appropriate: All changes relate to the PR title, or explanations provided for why they're included
  • Video demo: A small video demo showing changes works as expected and did not break any existing functionality using Agent Playground (if applicable)

Testing

  • Automated tests added/updated (if applicable)
  • All tests pass
  • Make sure both restaurant_agent.ts and realtime_agent.ts work properly (for major changes)

Additional Notes


Note to reviewers: Please ensure the pre-review checklist is completed before starting your review.

@lukasIO lukasIO requested a review from toubatbrian March 2, 2026 14:34
@changeset-bot
Copy link

changeset-bot bot commented Mar 2, 2026

🦋 Changeset detected

Latest commit: 2b22376

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 21 packages
Name Type
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-hedra Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-lemonslice Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-phonic Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-sarvam Patch
@livekit/agents-plugin-silero Patch
@livekit/agents-plugins-test Patch
@livekit/agents-plugin-xai Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment on lines 143 to 144
// Close the primary agent session if it exists
if (ctx._primaryAgentSession) {
Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 Cleanup code after try-catch is unprotected — process can still hang if cleanup throws

The PR wraps the entry function in a try-catch to ensure joinFuture.resolve() is reached, but the cleanup code that runs after the try-catch (lines 143-163) is itself unprotected. If any of ctx._primaryAgentSession.close(), ctx._onSessionEnd(), or room.disconnect() throws, the exception will propagate out of the async IIFE, and joinFuture.resolve() on line 163 will never execute — causing the exact same process-hang the PR is trying to fix.

Root cause and concrete throw path

ctx._onSessionEnd() at line 149 calls this.makeSessionReport(session) (agents/src/job.ts:295), which can throw in at least two places:

// job.ts:266
if (!targetSession) {
  throw new Error('Cannot prepare report, no AgentSession was found');
}
// job.ts:272
if (recorderIO && recorderIO.recording) {
  throw new Error('Cannot create the AgentSession report, the RecorderIO is still recording');
}

Neither of these throws is caught inside _onSessionEnd — only the uploadSessionReport call has a try-catch. So makeSessionReport throwing causes _onSessionEnd to reject, which causes the await at line 149 to throw, which propagates out of the IIFE, skipping joinFuture.resolve() on line 163.

Similarly, room.disconnect() at line 151 or ctx._primaryAgentSession.close() at line 145 could reject.

Impact: The process hangs indefinitely (never exits), which is the same bug the PR intends to fix.

(Refers to lines 143-163)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Contributor

Choose a reason for hiding this comment

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

@lukasIO Should we apply this suggestion as well?

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.

Memory leak due to alive processes after calls hangup

2 participants