]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Fix race on webtorrent RTC peer conn stats map
authorMatt Joiner <anacrolix@gmail.com>
Thu, 10 Jul 2025 06:32:45 +0000 (16:32 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 10 Jul 2025 06:32:45 +0000 (16:32 +1000)
webtorrent/tracker-client.go

index cf02b629b546ce44fbbfdd3a788a7df3a60023d4..51a861a720d20a6928420955e00d62e00f98b3f9 100644 (file)
@@ -45,6 +45,7 @@ type TrackerClient struct {
        WebsocketTrackerHttpHeader func() http.Header
        ICEServers                 []webrtc.ICEServer
 
+       // Used for stats only I think.
        rtcPeerConns map[string]*wrappedPeerConnection
 
        // callbacks
@@ -247,8 +248,11 @@ func (tc *TrackerClient) Announce(event tracker.AnnounceEvent, infoHash [20]byte
        // save the leecher peer connections
        tc.storePeerConnection(fmt.Sprintf("%x", randOfferId[:]), pc)
 
+       // Register handler in another package.
        pc.OnClose(func() {
-               delete(tc.rtcPeerConns, offerIDBinary)
+               // Asynchronous because we might hold the current lock here, depending on where Close is
+               // called from.
+               go tc.removePeerConn(offerIDBinary)
        })
 
        tc.Logger.Levelf(log.Debug, "announcing offer")
@@ -268,6 +272,13 @@ func (tc *TrackerClient) Announce(event tracker.AnnounceEvent, infoHash [20]byte
        return err
 }
 
+// Remove peer conn so it doesn't come up in stats.
+func (tc *TrackerClient) removePeerConn(key string) {
+       tc.mu.Lock()
+       defer tc.mu.Unlock()
+       delete(tc.rtcPeerConns, key)
+}
+
 func (tc *TrackerClient) announce(event tracker.AnnounceEvent, infoHash [20]byte, offers []outboundOffer) error {
        request, err := tc.GetAnnounceRequest(event, infoHash)
        if err != nil {
@@ -441,8 +452,6 @@ func (tc *TrackerClient) handleAnswer(offerId string, answer webrtc.SessionDescr
 func (tc *TrackerClient) storePeerConnection(offerId string, pc *wrappedPeerConnection) {
        tc.mu.Lock()
        defer tc.mu.Unlock()
-       if tc.rtcPeerConns == nil {
-               tc.rtcPeerConns = make(map[string]*wrappedPeerConnection)
-       }
+       g.MakeMapIfNil(&tc.rtcPeerConns)
        tc.rtcPeerConns[offerId] = pc
 }