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

Make pc.Close wait on spawned goroutines to close #2798

Merged
merged 1 commit into from
Jul 2, 2024

Conversation

edaniels
Copy link
Member

@edaniels edaniels commented Jul 1, 2024

This ensures no goroutines are running when a PeerConnection is closed. I'd also like to backport this into v3 so that existing users can benefit. Relies on pion/ice#706 (tests will fail before that's in).

@edaniels edaniels requested a review from Sean-Der July 1, 2024 16:40
Copy link

codecov bot commented Jul 1, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 79.18%. Comparing base (f229661) to head (9b3e4b2).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2798      +/-   ##
==========================================
+ Coverage   79.13%   79.18%   +0.04%     
==========================================
  Files          89       89              
  Lines        8249     8268      +19     
==========================================
+ Hits         6528     6547      +19     
  Misses       1255     1255              
  Partials      466      466              
Flag Coverage Δ
go 80.81% <100.00%> (+0.04%) ⬆️
wasm 64.98% <ø> (ø)

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.

@Sean-Der
Copy link
Member

Sean-Der commented Jul 1, 2024

What’s the downside of making this the default behavior? Close takes longer?

I would say having two Close methods is worse then blocking in Go. It’s a extra cognitive load on the user

@edaniels
Copy link
Member Author

edaniels commented Jul 1, 2024

What’s the downside of making this the default behavior? Close takes longer?

I would say having two Close methods is worse then blocking in Go. It’s a extra cognitive load on the user

I'm cool with it being just one 8). Yes it'll just take longer. If it ever locks up for too long, we have a bug, which I prefer to be caught this way.

@edaniels
Copy link
Member Author

edaniels commented Jul 1, 2024

@Sean-Der updated Close instead.

@edaniels edaniels changed the title Add PeerConneciton.CloseCleanly Add PeerConneciton.Close Jul 1, 2024
@edaniels edaniels changed the title Add PeerConneciton.Close Make pc.Close wait on spawned goroutines to close Jul 1, 2024
datachannel.go Outdated
@@ -457,6 +460,12 @@ func (d *DataChannel) Close() error {
return nil
}

if d.readLoopActive != nil {
Copy link
Member

Choose a reason for hiding this comment

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

What do you think of dropping the nil check or logging a error message? I would rather have a crash/error message over inconsistent behavior.

Is closing a nil chan safe?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm okay doing a check for !d.api.settingEngine.detach.DataChannels instead, which is when we have a read loop. What would you prefer?

@@ -2268,8 +2291,11 @@ func (pc *PeerConnection) startTransports(iceRole ICERole, dtlsRole DTLSRole, re
}

pc.dtlsTransport.internalOnCloseHandler = func() {
pc.log.Info("Closing PeerConnection from DTLS CloseNotify")
if pc.isClosed.get() {
Copy link
Member

Choose a reason for hiding this comment

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

Is this getting fired multiple times right now?

Copy link
Member Author

Choose a reason for hiding this comment

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

It doesn't, but it can get fired from a DTLS closenotify while Close is happening, if the timing is right.

@@ -2097,6 +2114,19 @@ func (pc *PeerConnection) Close() error {
// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #11)
pc.updateConnectionState(pc.ICEConnectionState(), pc.dtlsTransport.State())

// non-canon steps
pc.sctpTransport.lock.Lock()
Copy link
Member Author

@edaniels edaniels Jul 1, 2024

Choose a reason for hiding this comment

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

@Sean-Der I moved these steps lower. I also made Close not block since it's not clear to me if that's allowed per the spec. AFAICT, a normal Close waits for both sides to see the reset stream and let reads come through in the meantime.

@edaniels edaniels force-pushed the clean_close branch 2 times, most recently from d7d555d to 49b7f46 Compare July 1, 2024 20:33
@edaniels
Copy link
Member Author

edaniels commented Jul 1, 2024

@Sean-Der cleaned up Close and made a blocking/non-blocking version to behave with when/where it's called (PeerConnection.Close (block) or directly (cannot block due to spec))

@Sean-Der
Copy link
Member

Sean-Der commented Jul 2, 2024

Thanks for doing this @edaniels! Hopefully this means one less annoyed user :)

Were you doing tests that looked for leaked goroutines in a code base that used Pion?

@Sean-Der Sean-Der merged commit 7c8bfbd into pion:master Jul 2, 2024
17 checks passed
@edaniels
Copy link
Member Author

edaniels commented Jul 2, 2024

Yep! It came up for Viam and I saw this years ago and we just ignored it. It's become more important as more sophisticated testing has ramped up.

@edaniels
Copy link
Member Author

edaniels commented Jul 2, 2024

I'll put up a backport later!

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.

None yet

2 participants