Skip to content

Commit 5380e42

Browse files
Possible race in local_participant
1 parent d0887ac commit 5380e42

2 files changed

Lines changed: 15 additions & 1 deletion

File tree

include/livekit/local_participant.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@ class LIVEKIT_API LocalParticipant : public Participant {
246246
/// prune expired @c weak_ptr entries.
247247
mutable TrackMap published_tracks_by_sid_;
248248

249+
/// Guards @ref published_tracks_by_sid_. The map is written from the
250+
/// application thread (@ref publishTrack / @ref unpublishTrack) and both read
251+
/// and pruned from the FFI callback thread (@ref trackPublications /
252+
/// @ref findTrackPublication, reached via Room::onEvent). Without this lock
253+
/// those concurrent accesses race and free map nodes out from under each
254+
/// other (heap-use-after-free). Leaf lock: no other lock is taken while held.
255+
mutable std::mutex published_tracks_mutex_;
256+
249257
std::unordered_map<std::string, RpcHandler> rpc_handlers_;
250258

251259
// Shared state for RPC invocation tracking. Using shared_ptr so the state

src/local_participant.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,10 @@ void LocalParticipant::publishTrack(const std::shared_ptr<Track>& track, const T
197197
auto publication = std::make_shared<LocalTrackPublication>(owned_pub);
198198

199199
const std::string sid = publication->sid();
200-
published_tracks_by_sid_[sid] = std::weak_ptr<Track>(track);
200+
{
201+
const std::scoped_lock<std::mutex> lock(published_tracks_mutex_);
202+
published_tracks_by_sid_[sid] = std::weak_ptr<Track>(track);
203+
}
201204

202205
track->setPublication(publication);
203206
}
@@ -237,6 +240,7 @@ void LocalParticipant::unpublishTrack(const std::string& track_sid) {
237240

238241
fut.get();
239242

243+
const std::scoped_lock<std::mutex> lock(published_tracks_mutex_);
240244
if (auto it = published_tracks_by_sid_.find(track_sid); it != published_tracks_by_sid_.end()) {
241245
if (auto t = it->second.lock()) {
242246
t->setPublication(nullptr);
@@ -247,6 +251,7 @@ void LocalParticipant::unpublishTrack(const std::string& track_sid) {
247251

248252
LocalParticipant::PublicationMap LocalParticipant::trackPublications() const {
249253
PublicationMap out;
254+
const std::scoped_lock<std::mutex> lock(published_tracks_mutex_);
250255
for (auto it = published_tracks_by_sid_.begin(); it != published_tracks_by_sid_.end();) {
251256
auto t = it->second.lock();
252257
if (!t) {
@@ -443,6 +448,7 @@ void LocalParticipant::handleRpcMethodInvocation(uint64_t invocation_id, const s
443448
}
444449

445450
std::shared_ptr<TrackPublication> LocalParticipant::findTrackPublication(const std::string& sid) const {
451+
const std::scoped_lock<std::mutex> lock(published_tracks_mutex_);
446452
auto it = published_tracks_by_sid_.find(sid);
447453
if (it == published_tracks_by_sid_.end()) {
448454
return nullptr;

0 commit comments

Comments
 (0)