Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix concurrent pc.GracefulClose #2887

Merged
merged 1 commit into from
Aug 26, 2024

Conversation

edaniels
Copy link
Member

@edaniels edaniels commented Aug 24, 2024

@dgottlieb found an issue in the wild where if concurrent GracefulCloses happen, my wonky atomic bool logic could go awry and cause a leak of sorts and no actual graceful closure. I took some time to clean up the naming and comments in this code while working on the fix which is mainly to wrap a lock around the two bool operations, but also to have a more stringent series of operations when Graceful and normal close are overlapping.

@edaniels edaniels requested a review from Sean-Der August 24, 2024 06:02
Copy link

codecov bot commented Aug 24, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 79.00%. Comparing base (64a837f) to head (3989fcf).
Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2887      +/-   ##
==========================================
+ Coverage   78.96%   79.00%   +0.03%     
==========================================
  Files          89       89              
  Lines        8461     8477      +16     
==========================================
+ Hits         6681     6697      +16     
- Misses       1294     1295       +1     
+ Partials      486      485       -1     
Flag Coverage Δ
go 80.56% <100.00%> (+0.04%) ⬆️
wasm 65.11% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@edaniels edaniels force-pushed the graceful_close_self_deadlock_fix branch 6 times, most recently from 1ab3574 to 2e5e1bf Compare August 24, 2024 06:22
@edaniels edaniels changed the title Fix pc.GracefulClose concurrency > 2 Fix pc.GracefulClose at concurrency > 2 Aug 24, 2024
@edaniels edaniels force-pushed the graceful_close_self_deadlock_fix branch 6 times, most recently from 363bc7b to 69d2e1a Compare August 24, 2024 06:40
@edaniels edaniels changed the title Fix pc.GracefulClose at concurrency > 2 Fix concurrent pc.GracefulClose Aug 24, 2024
@edaniels edaniels force-pushed the graceful_close_self_deadlock_fix branch from 69d2e1a to 1215aab Compare August 24, 2024 06:48
// want to make graceful and normal closure one time operations in order
// to avoid any double closure errors from cropping up. However, there are
// some overlapping close cases when both normal and graceful close are used
// that should be idempotent, but be cautioned when writing new close behavior

Choose a reason for hiding this comment

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

I came into this function thinking that it wouldn't make sense for applications to make concurrent graceful + non-graceful close calls. I think it would be fine to declare that usage undefined.

But allowing for both is obviously better if the idempotency requirement is not burdensome.

}

// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #3)
pc.signalingState.Set(SignalingStateClosed)
if shouldGracefullyClose && !isAlreadyGracefullyClosingOrClosed {

Choose a reason for hiding this comment

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

I suspect this is "belts and suspenders" logic -- but I expect isAlreadyGracefullyClosingOrClosed can only be false here.

Was the risk of double closing the reason this was in its own block rather than being put directly into the doGracefulClose lambda?

Copy link
Member Author

@edaniels edaniels Aug 26, 2024

Choose a reason for hiding this comment

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

Nope you're right. I think this was some left over boolean logic that can be folded into the lambda now. Nice catch.

Edit: I'll actually just keep the code here and remove the second condition to preserve the early defer logic to prevent against any panics in the many libraries that are subsequently called into here. If there were a lot less going on here in terms of stopping/closing, I would drop it into that lambda or if the function was smaller, use a named return value for err, defer the close logic, and update the error.

}

// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #3)
pc.signalingState.Set(SignalingStateClosed)

Choose a reason for hiding this comment

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

I've double checked that the place this line moved to was equivalent.

I suppose it must be the case that once someone calls close and moving the signaling state into SignalingStateClosed-- it's impossible for the signaling state to leave SignalingStateClosed?

Given the old + new code for Close do nothing on subsequent calls.

Copy link
Member Author

Choose a reason for hiding this comment

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

So nothings prevents that state from moving out of Closed, but yeah, the logic in here doesn't have move to anything else other than Closed.

@edaniels edaniels force-pushed the graceful_close_self_deadlock_fix branch from 1215aab to 3989fcf Compare August 26, 2024 11:38
@edaniels
Copy link
Member Author

Got Sean's approval offline

@edaniels edaniels merged commit 9a61d68 into pion:master Aug 26, 2024
18 of 19 checks passed
@edaniels edaniels deleted the graceful_close_self_deadlock_fix branch August 26, 2024 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants