Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion obs-studio-server/source/osn-volmeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ void osn::Volmeter::Attach(void *data, const int64_t id, const std::vector<ipc::
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid Meter reference.");
}

auto source = osn::Source::Manager::GetInstance().find(uid_source);
OBSSourceAutoRelease source = osn::Source::Manager::GetInstance().findAndRef(uid_source);
if (!source) {
PRETTY_ERROR_RETURN(ErrorCode::InvalidReference, "Invalid Source reference.");
}
Expand All @@ -126,6 +126,7 @@ void osn::Volmeter::Attach(void *data, const int64_t id, const std::vector<ipc::
}

meter->uid_source = uid_source;
meter->source_ref = std::move(source);

rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
AUTO_DEBUG;
Expand All @@ -143,6 +144,7 @@ void osn::Volmeter::Detach(void *data, const int64_t id, const std::vector<ipc::

meter->uid_source = INVALID_ID;
obs_volmeter_detach_source(meter->self);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still calls obs_volmeter_detach_source() while holding OSN's global mtx. With the new strong source_ref, libobs detach can now reliably reach obs_source_remove_audio_capture_callback(), which takes source->audio_cb_mutex.

The audio thread can hold that mutex while dispatching volmeter_source_data_received -> signal_levels_updated -> Volmeter::OBSCallback, where OSN tries to take mtx. That gives a deadlock opportunity: detach thread holds mtx waiting for audio_cb_mutex, audio thread holds audio_cb_mutex waiting for mtx.

Can we split the lock scope here? Grab the shared_ptr<Volmeter> under mtx, clear OSN state as needed, release mtx, then call obs_volmeter_detach_source(), and only release source_ref after detach completes.

meter->source_ref = nullptr; // release after detach, so the weak-ref upgrade inside detach still succeeds

rval.push_back(ipc::value((uint64_t)ErrorCode::Ok));
AUTO_DEBUG;
Expand Down
4 changes: 4 additions & 0 deletions obs-studio-server/source/osn-volmeter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <queue>
#include <array>
#include "obs.h"
#include <obs.hpp>
#include "utility.hpp"

extern std::mutex mtx;
Expand Down Expand Up @@ -52,6 +53,9 @@ class Volmeter {
utility::unique_id::id_t id = INVALID_ID;
utility::unique_id::id_t uid_source = INVALID_ID;

// Kept alive while attached so detach can always remove the audio capture callback before the volmeter is freed.
OBSSourceAutoRelease source_ref;

struct AudioData {
std::array<float, MAX_AUDIO_CHANNELS> magnitude{};
std::array<float, MAX_AUDIO_CHANNELS> peak{};
Expand Down
Loading