Skip to content

Fix unpublish_track deadlock on FFI error#752

Open
apoorva-01 wants to merge 1 commit into
livekit:mainfrom
apoorva-01:fix/565-unpublish-deadlock
Open

Fix unpublish_track deadlock on FFI error#752
apoorva-01 wants to merge 1 commit into
livekit:mainfrom
apoorva-01:fix/565-unpublish-deadlock

Conversation

@apoorva-01

@apoorva-01 apoorva-01 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

unpublish_track only calls queue.task_done() at the bottom of the try, after the error raise.
So when the FFI reports an error the raise skips it, and that event stays on the room queue unconsumed. Room._listen_task does put_nowait(event) then await join(), so one stuck event hangs the whole room loop.

Moved task_done() to right after wait_for() returns, before the error check. The error still propagates and the queue always gets released.

Added a regression test that drives the same put/join loop. It hangs without the fix and passes with it.

on thing:publish_track right above has the same pattern. Left it out to keep this focused - happy to fix it here or in a follow-up.

closes #565

task_done() ran after the error raise, so a failed unpublish left the room queue's join() waiting forever and stalled the event loop.

@devin-ai-integration devin-ai-integration Bot 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.

Devin Review found 1 potential issue.

Open in Devin Review

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.

🔴 Track publishing errors stall the room event loop with the same deadlock fixed for unpublishing

The room queue event is not marked as done (queue.task_done() at livekit-rtc/livekit/rtc/participant.py:831) when a publish error is raised (livekit-rtc/livekit/rtc/participant.py:824), so the room event loop blocks forever waiting on the unconsumed event.

Impact: When publishing a track fails, the room stops processing all subsequent events, effectively freezing the connection.

Same deadlock pattern as the unpublish_track fix in this PR

This PR fixes the deadlock in unpublish_track by moving queue.task_done() before the error check. However, publish_track has the identical pattern:

  1. queue = self._room_queue.subscribe() at livekit-rtc/livekit/rtc/participant.py:816
  2. await queue.wait_for(...) at livekit-rtc/livekit/rtc/participant.py:819 — returns an event that the caller must mark done
  3. Error check at livekit-rtc/livekit/rtc/participant.py:823-824 raises PublishTrackError before task_done() at line 831
  4. The finally block at line 833-834 only calls unsubscribe, not task_done()

The room event loop at livekit-rtc/livekit/rtc/room.py:714-715 does:

self._room_queue.put_nowait(event)
await self._room_queue.join()

Since join() waits for all subscribers to call task_done(), the unconsumed event blocks the room event loop permanently.

The fix should mirror the unpublish_track fix: move queue.task_done() to immediately after wait_for returns, before the error check.

(Refers to lines 823-831)

Open in Devin Review

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

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.

Unpublish track failure causes deadlock

1 participant