Bug 1859200 permit AppendMessage() with other ControlMessageInterface objects r=pehrsons

A similar assertion will be added to new methods for other
ControlMessageInterface objects in a subsequent patch.

MediaTrackGraphImpl::OpenAudioInput() and
AudioListener::SendListenerEngineEvent() are two of a number of cases that
construct a ControlMessage with a null track.

Differential Revision: https://phabricator.services.mozilla.com/D191061
This commit is contained in:
Karl Tomlinson 2023-10-17 00:02:50 +00:00
parent ce078b9839
commit 8a25ccdeef
4 changed files with 28 additions and 23 deletions

View file

@ -1284,7 +1284,7 @@ void MediaTrackGraphImpl::ProduceDataForTracksBlockByBlock(
}
void MediaTrackGraphImpl::RunMessageAfterProcessing(
UniquePtr<ControlMessage> aMessage) {
UniquePtr<ControlMessageInterface> aMessage) {
MOZ_ASSERT(OnGraphThread());
if (mFrontMessageQueue.IsEmpty()) {
@ -1303,7 +1303,7 @@ void MediaTrackGraphImpl::RunMessagesInQueue() {
// batch corresponding to an event loop task). This isolates the performance
// of different scripts to some extent.
for (uint32_t i = 0; i < mFrontMessageQueue.Length(); ++i) {
nsTArray<UniquePtr<ControlMessage>>& messages =
nsTArray<UniquePtr<ControlMessageInterface>>& messages =
mFrontMessageQueue[i].mMessages;
for (uint32_t j = 0; j < messages.Length(); ++j) {
@ -1868,7 +1868,8 @@ void MediaTrackGraphImpl::RunInStableState(bool aSourceIsMTG) {
// When we're doing a forced shutdown, pending control messages may be
// run on the main thread via RunDuringShutdown. Those messages must
// run without the graph monitor being held. So, we collect them here.
nsTArray<UniquePtr<ControlMessage>> controlMessagesToRunDuringShutdown;
nsTArray<UniquePtr<ControlMessageInterface>>
controlMessagesToRunDuringShutdown;
{
MonitorAutoLock lock(mMonitor);
@ -2031,10 +2032,9 @@ void MediaTrackGraphImpl::SignalMainThreadCleanup() {
EnsureStableStateEventPosted();
}
void MediaTrackGraphImpl::AppendMessage(UniquePtr<ControlMessage> aMessage) {
void MediaTrackGraphImpl::AppendMessage(
UniquePtr<ControlMessageInterface> aMessage) {
MOZ_ASSERT(NS_IsMainThread(), "main thread only");
MOZ_RELEASE_ASSERT(!aMessage->GetTrack() ||
!aMessage->GetTrack()->IsDestroyed());
MOZ_DIAGNOSTIC_ASSERT(mMainThreadTrackCount > 0 || mMainThreadPortCount > 0);
if (!mGraphDriverRunning &&

View file

@ -72,12 +72,14 @@ struct TrackUpdate {
* This represents a message run on the graph thread to modify track or graph
* state. These are passed from main thread to graph thread through
* AppendMessage(), or scheduled on the graph thread with
* RunMessageAfterProcessing(). A ControlMessage
* always has a weak reference to a particular affected track.
* RunMessageAfterProcessing(). A ControlMessage often has
* a weak reference to a particular affected track.
*/
class ControlMessage : public MediaTrack::ControlMessageInterface {
public:
explicit ControlMessage(MediaTrack* aTrack) : mTrack(aTrack) {}
explicit ControlMessage(MediaTrack* aTrack) : mTrack(aTrack) {
MOZ_RELEASE_ASSERT(!aTrack || !NS_IsMainThread() || !aTrack->IsDestroyed());
}
MediaTrack* GetTrack() { return mTrack; }
@ -90,7 +92,7 @@ class ControlMessage : public MediaTrack::ControlMessageInterface {
class MessageBlock {
public:
nsTArray<UniquePtr<ControlMessage>> mMessages;
nsTArray<UniquePtr<MediaTrack::ControlMessageInterface>> mMessages;
};
/**
@ -180,10 +182,10 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
*/
void ApplyTrackUpdate(TrackUpdate* aUpdate) MOZ_REQUIRES(mMonitor);
/**
* Append a ControlMessage to the message queue. This queue is drained
* Append a control message to the message queue. This queue is drained
* during RunInStableState; the messages will run on the graph thread.
*/
virtual void AppendMessage(UniquePtr<ControlMessage> aMessage);
virtual void AppendMessage(UniquePtr<ControlMessageInterface> aMessage);
/**
* Dispatches a runnable from any thread to the correct main thread for this
@ -330,7 +332,7 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
* Schedules |aMessage| to run after processing, at a time when graph state
* can be changed. Graph thread.
*/
void RunMessageAfterProcessing(UniquePtr<ControlMessage> aMessage);
void RunMessageAfterProcessing(UniquePtr<ControlMessageInterface> aMessage);
/**
* Resolve the GraphStartedPromise when the driver has started processing on
@ -664,7 +666,7 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
* Main-thread view of the number of ports in this graph, to catch bugs.
*
* When this becomes zero, and mMainThreadTrackCount is 0, the graph is
* marked as forbidden to add more ControlMessages to. It will be shut down
* marked as forbidden to add more control messages to. It will be shut down
* shortly after.
*/
size_t mMainThreadPortCount = 0;
@ -772,7 +774,7 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
// MediaTrackGraph normally does its work without holding mMonitor, so it is
// not safe to just grab mMonitor from some thread and start monkeying with
// the graph. Instead, communicate with the graph thread using provided
// mechanisms such as the ControlMessage queue.
// mechanisms such as the control message queue.
Monitor mMonitor;
// Data guarded by mMonitor (must always be accessed with mMonitor held,
@ -925,7 +927,7 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
* immediately because we want all messages between stable states to be
* processed as an atomic batch.
*/
nsTArray<UniquePtr<ControlMessage>> mCurrentTaskMessageQueue;
nsTArray<UniquePtr<ControlMessageInterface>> mCurrentTaskMessageQueue;
/**
* True from when RunInStableState sets mLifecycleState to LIFECYCLE_RUNNING,
* until RunInStableState has determined that mLifecycleState is >
@ -995,7 +997,7 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
#ifdef DEBUG
/**
* Used to assert when AppendMessage() runs ControlMessages synchronously.
* Used to assert when AppendMessage() runs control messages synchronously.
*/
bool mCanRunMessagesSynchronously;
#endif

View file

@ -21,6 +21,7 @@ using namespace mozilla::media;
using testing::AssertionResult;
using testing::NiceMock;
using testing::Return;
using ControlMessageInterface = MediaTrack::ControlMessageInterface;
constexpr uint32_t kNoFlags = 0;
constexpr TrackRate kRate = 44100;
@ -40,7 +41,7 @@ class MockTestGraph : public MediaTrackGraphImpl {
}
MOCK_CONST_METHOD0(OnGraphThread, bool());
MOCK_METHOD1(AppendMessage, void(UniquePtr<ControlMessage>));
MOCK_METHOD1(AppendMessage, void(UniquePtr<ControlMessageInterface>));
protected:
~MockTestGraph() = default;
@ -320,8 +321,9 @@ TEST_F(TestAudioDecoderInputTrack, VolumeChange) {
// one for setting the track's volume, another for the track destruction.
EXPECT_CALL(*mGraph, AppendMessage)
.Times(2)
.WillOnce([](UniquePtr<ControlMessage> aMessage) { aMessage->Run(); })
.WillOnce([](UniquePtr<ControlMessage> aMessage) {});
.WillOnce(
[](UniquePtr<ControlMessageInterface> aMessage) { aMessage->Run(); })
.WillOnce([](UniquePtr<ControlMessageInterface> aMessage) {});
// The default volume is 1.0.
float expectedVolume = 1.0;
@ -419,8 +421,9 @@ TEST_F(TestAudioDecoderInputTrack, PlaybackRateChange) {
// one for setting the track's playback, another for the track destruction.
EXPECT_CALL(*mGraph, AppendMessage)
.Times(2)
.WillOnce([](UniquePtr<ControlMessage> aMessage) { aMessage->Run(); })
.WillOnce([](UniquePtr<ControlMessage> aMessage) {});
.WillOnce(
[](UniquePtr<ControlMessageInterface> aMessage) { aMessage->Run(); })
.WillOnce([](UniquePtr<ControlMessageInterface> aMessage) {});
// Changing the playback rate.
float expectedPlaybackRate = 2.0;

View file

@ -39,7 +39,7 @@ class MockGraphImpl : public MediaTrackGraphImpl {
}
MOCK_CONST_METHOD0(OnGraphThread, bool());
MOCK_METHOD1(AppendMessage, void(UniquePtr<ControlMessage>));
MOCK_METHOD1(AppendMessage, void(UniquePtr<ControlMessageInterface>));
protected:
~MockGraphImpl() = default;