Browse Source

hls: fix freeze in case of muxing errors (#3135) (#3150)

pull/3151/head
Alessandro Ros 2 years ago committed by GitHub
parent
commit
1d4ea2cd9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      internal/asyncwriter/async_writer.go
  2. 22
      internal/asyncwriter/async_writer_test.go
  3. 15
      internal/servers/hls/muxer.go
  4. 2
      internal/servers/rtmp/conn.go
  5. 2
      internal/servers/srt/conn.go
  6. 3
      internal/servers/webrtc/session.go
  7. 1
      internal/test/source_tester.go

1
internal/asyncwriter/async_writer.go

@ -50,6 +50,7 @@ func (w *Writer) Error() chan error {
func (w *Writer) run() { func (w *Writer) run() {
w.err <- w.runInner() w.err <- w.runInner()
close(w.err)
} }
func (w *Writer) runInner() error { func (w *Writer) runInner() error {

22
internal/asyncwriter/async_writer_test.go

@ -0,0 +1,22 @@
package asyncwriter
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
func TestAsyncWriter(t *testing.T) {
w := New(512, nil)
w.Start()
defer w.Stop()
w.Push(func() error {
return fmt.Errorf("testerror")
})
err := <-w.Error()
require.EqualError(t, err, "testerror")
}

15
internal/servers/hls/muxer.go

@ -165,6 +165,12 @@ func (m *muxer) runInner() error {
recreateTimer = emptyTimer() recreateTimer = emptyTimer()
} }
defer func() {
if mi != nil {
mi.close()
}
}()
var activityCheckTimer *time.Timer var activityCheckTimer *time.Timer
if m.remoteAddr != "" { if m.remoteAddr != "" {
activityCheckTimer = time.NewTimer(closeCheckPeriod) activityCheckTimer = time.NewTimer(closeCheckPeriod)
@ -178,13 +184,12 @@ func (m *muxer) runInner() error {
req.res <- mi req.res <- mi
case err := <-instanceError: case err := <-instanceError:
mi.close()
if m.remoteAddr != "" { if m.remoteAddr != "" {
return err return err
} }
m.Log(logger.Error, err.Error()) m.Log(logger.Error, err.Error())
mi.close()
mi = nil mi = nil
instanceError = make(chan error) instanceError = make(chan error)
recreateTimer = time.NewTimer(recreatePause) recreateTimer = time.NewTimer(recreatePause)
@ -215,17 +220,11 @@ func (m *muxer) runInner() error {
case <-activityCheckTimer.C: case <-activityCheckTimer.C:
t := time.Unix(0, atomic.LoadInt64(m.lastRequestTime)) t := time.Unix(0, atomic.LoadInt64(m.lastRequestTime))
if time.Since(t) >= closeAfterInactivity { if time.Since(t) >= closeAfterInactivity {
if mi != nil {
mi.close()
}
return fmt.Errorf("not used anymore") return fmt.Errorf("not used anymore")
} }
activityCheckTimer = time.NewTimer(closeCheckPeriod) activityCheckTimer = time.NewTimer(closeCheckPeriod)
case <-m.ctx.Done(): case <-m.ctx.Done():
if mi != nil {
mi.close()
}
return errors.New("terminated") return errors.New("terminated")
} }
} }

2
internal/servers/rtmp/conn.go

@ -237,10 +237,10 @@ func (c *conn) runRead(conn *rtmp.Conn, u *url.URL) error {
c.nconn.SetReadDeadline(time.Time{}) c.nconn.SetReadDeadline(time.Time{})
writer.Start() writer.Start()
defer writer.Stop()
select { select {
case <-c.ctx.Done(): case <-c.ctx.Done():
writer.Stop()
return fmt.Errorf("terminated") return fmt.Errorf("terminated")
case err := <-writer.Error(): case err := <-writer.Error():

2
internal/servers/srt/conn.go

@ -327,10 +327,10 @@ func (c *conn) runRead(req srtNewConnReq, streamID *streamID) (bool, error) {
sconn.SetReadDeadline(time.Time{}) sconn.SetReadDeadline(time.Time{})
writer.Start() writer.Start()
defer writer.Stop()
select { select {
case <-c.ctx.Done(): case <-c.ctx.Done():
writer.Stop()
return true, fmt.Errorf("terminated") return true, fmt.Errorf("terminated")
case err := <-writer.Error(): case err := <-writer.Error():

3
internal/servers/webrtc/session.go

@ -612,17 +612,16 @@ func (s *session) runRead() (int, error) {
defer onUnreadHook() defer onUnreadHook()
writer.Start() writer.Start()
defer writer.Stop()
select { select {
case <-pc.Disconnected(): case <-pc.Disconnected():
writer.Stop()
return 0, fmt.Errorf("peer connection closed") return 0, fmt.Errorf("peer connection closed")
case err := <-writer.Error(): case err := <-writer.Error():
return 0, err return 0, err
case <-s.ctx.Done(): case <-s.ctx.Done():
writer.Stop()
return 0, fmt.Errorf("terminated") return 0, fmt.Errorf("terminated")
} }
} }

1
internal/test/source_tester.go

@ -69,6 +69,7 @@ func (t *SourceTester) SetReady(req defs.PathSourceStaticSetReadyReq) defs.PathS
) )
t.writer = asyncwriter.New(2048, t) t.writer = asyncwriter.New(2048, t)
t.stream.AddReader(t.writer, req.Desc.Medias[0], req.Desc.Medias[0].Formats[0], func(u unit.Unit) error { t.stream.AddReader(t.writer, req.Desc.Medias[0], req.Desc.Medias[0].Formats[0], func(u unit.Unit) error {
t.Unit <- u t.Unit <- u
close(t.Unit) close(t.Unit)

Loading…
Cancel
Save