pion / webrtc

Pure Go implementation of the WebRTC API
https://pion.ly
MIT License
13.37k stars 1.63k forks source link

Panic on Read() in rtpreceiver.go #2322

Open MikolajMGT opened 1 year ago

MikolajMGT commented 1 year ago

Your environment.

Hi, I've got following panic error several times last week:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x1686af0]

goroutine 605202 [running]:
github.com/pion/webrtc/v3.(*RTPReceiver).Read(0xc004320ea0, {0xc0074a4c00, 0x5b4, 0x5b4})
    /Users/mikolaj-praca/go/pkg/mod/github.com/pion/webrtc/v3@v3.1.6/rtpreceiver.go:182 +0x90
github.com/pion/webrtc/v3.(*RTPReceiver).ReadRTCP(0xc004320ea0)
    /Users/mikolaj-praca/go/pkg/mod/github.com/pion/webrtc/v3@v3.1.6/rtpreceiver.go:207 +0x65
gitlab.com/evemeta/zucasa/backend/sfu/gateway/app/v1/sfu.(*User).onTrack.func3()
    /Users/mikolaj-praca/GolandProjects/zucasa/backend/sfu/gateway/app/v1/sfu/user.go:417 +0x36
created by gitlab.com/evemeta/zucasa/backend/sfu/gateway/app/v1/sfu.(*User).onTrack
    /Users/mikolaj-praca/GolandProjects/zucasa/backend/sfu/gateway/app/v1/sfu/user.go:415 +0x45e

According to stack trace, the issue itself occurs in following method of rtpreceiver.go:

// Read reads incoming RTCP for this RTPReceiver
func (r *RTPReceiver) Read(b []byte) (n int, a interceptor.Attributes, err error) {
    select {
    case <-r.received:
        return r.tracks[0].rtcpInterceptor.Read(b, a) // <--- here
    case <-r.closed:
        return 0, nil, io.ErrClosedPipe
    }
}

Unfortunately I don't know how to reproduce it yet. But at this point I would like to clarify: is the panic expected behavior resulting from my incorrect implementation, or maybe there is some missing error handling / nil check here?

Best Regards Nicolas

Sean-Der commented 5 months ago

Sorry I never got to this @MikolajMGT!

Did this get resolved/are you still seeing this issue?

generalomosco commented 4 months ago

The problem is using numeric rid rather than alphabetic character in the rid values, it is safe when you use receiver.ReadSimulcastRTCP(track.RID()) with any rid character on simulcast receiver.

  pc.addTransceiver(track, {
            streams: [this.stream],
            direction: 'sendonly',
            sendEncodings = [
                { rid: "0", active: true, maxBitrate: 900000 },
                { rid: "1", active: true, maxBitrate: 300000, scaleResolutionDownBy: 2 },
                { rid: "2", active: true, maxBitrate: 100000, scaleResolutionDownBy: 4 }
            ]
        })

receiver.ReadRTCP() panic:


panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x18 pc=0x1003902]

goroutine 273 [running]:
github.com/pion/webrtc/v4.(*RTPReceiver).Read(0xc0000ef050, {0xc000710600, 0x5b4, 0x5b4})        
        C:/Users/Generalomosco/go/pkg/mod/github.com/pion/webrtc/v4@v4.0.0-beta.19/rtpreceiver.go:247 +0x82
github.com/pion/webrtc/v4.(*RTPReceiver).ReadRTCP(0xc0000ef050)
        C:/Users/Generalomosco/go/pkg/mod/github.com/pion/webrtc/v4@v4.0.0-beta.19/rtpreceiver.go:281 +0x5f
app-root/system/app/sfu.(*PeerRouter).NewReceiver.func1()
        C:/Users/Generalomosco/Desktop/go/home/stream/vcamm/servers/mediaserver/system/app/sfu/peerrouter.go:161 +0x27
created by app-root/system/app/sfu.(*PeerRouter).NewReceiver in goroutine 272
        C:/Users/Generalomosco/Desktop/go/home/stream/vcamm/servers/mediaserver/system/app/sfu/peerrouter.go:159 +0x116
exit status 2

The issue is that configureReceive already populate the track indexes based on the Encodings rid received before feeding the tracks with right information on various tracks, Maybe nil pointer check need to be added in r.tracks[0].rtcpInterceptor rtpreceiver.go#L247 to return error because browser are fishy when your app don't use simulcast and not bother to check if the receiver is simulcast


func (r *RTPReceiver) Read(b []byte) (n int, a interceptor.Attributes, err error) {
    select {
    case <-r.received:
        return r.tracks[0].rtcpInterceptor.Read(b, a)
    case <-r.closed:
        return 0, nil, io.ErrClosedPipe
    }
}