1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

HTTP-FLV: Crash when multiple viewers. v6.0.148 v7.0.5 (#4144)

I did some preliminary code inspection. The two playback endpoints share
the same `SrsLiveStream` instance. After the first one disconnects,
`alive_` is set to false.
```
  alive_ = true;
  err = do_serve_http(w, r);
  alive_ = false;
```

In the `SrsHttpStreamServer::http_unmount(SrsRequest* r)` function,
`stream->alive()` is already false, so `mux.unhandle` will free the
`SrsLiveStream`. This causes the other connection coroutine to return to
its execution environment after the `SrsLiveStream` instance has already
been freed.
```
    // Wait for cache and stream to stop.
    int i = 0;
    for (; i < 1024; i++) {
        if (!cache->alive() && !stream->alive()) {
            break;
        }
        srs_usleep(100 * SRS_UTIME_MILLISECONDS);
    }

    // Unmount the HTTP handler, which will free the entry. Note that we must free it after cache and
    // stream stopped for it uses it.
    mux.unhandle(entry->mount, stream.get());
```

`alive_` was changed from a `bool` to an `int` to ensure that
`mux.unhandle` is only executed after each connection's `serve_http` has
exited.

---------

Co-authored-by: liumengte <liumengte@visionular.com>
Co-authored-by: winlin <winlinvip@gmail.com>
This commit is contained in:
Bahamut 2024-08-15 12:00:42 +08:00 committed by winlin
parent e323215478
commit 3e811ba34a
7 changed files with 24 additions and 16 deletions

View file

@ -583,7 +583,7 @@ SrsLiveStream::SrsLiveStream(SrsRequest* r, SrsBufferCache* c)
cache = c;
req = r->copy()->as_http();
security_ = new SrsSecurity();
alive_ = false;
alive_viewers_ = 0;
}
SrsLiveStream::~SrsLiveStream()
@ -634,9 +634,9 @@ srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage
return srs_error_wrap(err, "http hook");
}
alive_ = true;
alive_viewers_++;
err = do_serve_http(w, r);
alive_ = false;
alive_viewers_--;
http_hooks_on_stop(r);
@ -645,7 +645,7 @@ srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage
bool SrsLiveStream::alive()
{
return alive_;
return alive_viewers_ > 0;
}
srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)