Bug 1415556 - P6. Ensure mLifecycleState member is always accessed safely. r=padenot

We only access mLifecycleState via a helper which strongly enforced how the member can be accessed.
Two non-safe accesses are corrected.

MozReview-Commit-ID: 6LYk7t4rSyB

--HG--
extra : rebase_source : 9727771e1b04ba1b39f5cf9a6cf94093b7e92b27
This commit is contained in:
Jean-Yves Avenard 2017-11-10 18:38:02 +01:00
Родитель 251f706a51
Коммит 66c39c273f
2 изменённых файлов: 52 добавлений и 31 удалений

Просмотреть файл

@ -566,7 +566,7 @@ MediaStreamGraphImpl::UpdateStreamOrder()
MonitorAutoLock mon(mMonitor);
if (CurrentDriver()->AsAudioCallbackDriver()->IsStarted() &&
!(CurrentDriver()->Switching())) {
if (mLifecycleState == LIFECYCLE_RUNNING) {
if (LifecycleStateRef() == LIFECYCLE_RUNNING) {
SystemClockDriver* driver = new SystemClockDriver(this);
CurrentDriver()->SwitchAtNextIteration(driver);
}
@ -583,7 +583,7 @@ MediaStreamGraphImpl::UpdateStreamOrder()
!CurrentDriver()->AsAudioCallbackDriver() &&
!switching) {
MonitorAutoLock mon(mMonitor);
if (mLifecycleState == LIFECYCLE_RUNNING) {
if (LifecycleStateRef() == LIFECYCLE_RUNNING) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
CurrentDriver()->SwitchAtNextIteration(driver);
}
@ -838,7 +838,7 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(MediaStream* aStream)
if (!CurrentDriver()->AsAudioCallbackDriver() &&
!switching) {
MonitorAutoLock mon(mMonitor);
if (mLifecycleState == LIFECYCLE_RUNNING) {
if (LifecycleStateRef() == LIFECYCLE_RUNNING) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
CurrentDriver()->SwitchAtNextIteration(driver);
}
@ -1000,7 +1000,7 @@ MediaStreamGraphImpl::OpenAudioInputImpl(int aID,
// Switch Drivers since we're adding input (to input-only or full-duplex)
MonitorAutoLock mon(mMonitor);
if (mLifecycleState == LIFECYCLE_RUNNING) {
if (LifecycleStateRef() == LIFECYCLE_RUNNING) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
driver->SetMicrophoneActive(true);
LOG(
@ -1076,7 +1076,7 @@ MediaStreamGraphImpl::CloseAudioInputImpl(AudioDataListener *aListener)
bool audioTrackPresent = AudioTrackPresent(shouldAEC);
MonitorAutoLock mon(mMonitor);
if (mLifecycleState == LIFECYCLE_RUNNING) {
if (LifecycleStateRef() == LIFECYCLE_RUNNING) {
GraphDriver* driver;
if (audioTrackPresent) {
// We still have audio output
@ -1465,7 +1465,7 @@ MediaStreamGraphImpl::UpdateMainThreadState()
LOG(LogLevel::Debug,
("MediaStreamGraph %p waiting for main thread cleanup", this));
// We'll shut down this graph object if it does not get restarted.
mLifecycleState = LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP;
LifecycleStateRef() = LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP;
// No need to Destroy streams here. The main-thread owner of each
// stream is responsible for calling Destroy on them.
return false;
@ -1543,7 +1543,7 @@ MediaStreamGraphImpl::ForceShutDown(media::ShutdownTicket* aShutdownTicket)
}
mForceShutDown = true;
mForceShutdownTicket = aShutdownTicket;
if (mLifecycleState == LIFECYCLE_THREAD_NOT_STARTED) {
if (LifecycleStateRef() == LIFECYCLE_THREAD_NOT_STARTED) {
// We *could* have just sent this a message to start up, so don't
// yank the rug out from under it. Tell it to startup and let it
// shut down.
@ -1658,7 +1658,7 @@ public:
// delete it.
NS_ASSERTION(mGraph->mForceShutDown || !mGraph->mRealtime,
"Not in forced shutdown?");
mGraph->mLifecycleState =
mGraph->LifecycleStateRef() =
MediaStreamGraphImpl::LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION;
}
return NS_OK;
@ -1737,11 +1737,11 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
"LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION"
};
if (mLifecycleState != LIFECYCLE_RUNNING) {
if (LifecycleStateRef() != LIFECYCLE_RUNNING) {
LOG(LogLevel::Debug,
("Running %p in stable state. Current state: %s",
this,
LifecycleState_str[mLifecycleState]));
LifecycleState_str[LifecycleStateRef()]));
}
runnables.SwapElements(mUpdateRunnables);
@ -1754,13 +1754,13 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
mStreamUpdates.Clear();
if (mCurrentTaskMessageQueue.IsEmpty()) {
if (mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP && IsEmpty()) {
if (LifecycleStateRef() == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP && IsEmpty()) {
// Complete shutdown. First, ensure that this graph is no longer used.
// A new graph graph will be created if one is needed.
// Asynchronously clean up old graph. We don't want to do this
// synchronously because it spins the event loop waiting for threads
// to shut down, and we don't want to do that in a stable state handler.
mLifecycleState = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
LifecycleStateRef() = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
LOG(LogLevel::Debug,
("Sending MediaStreamGraphShutDownRunnable %p", this));
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphShutDownRunnable(this );
@ -1777,7 +1777,7 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
}
}
} else {
if (mLifecycleState <= LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) {
if (LifecycleStateRef() <= LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) {
MessageBlock* block = mBackMessageQueue.AppendElement();
block->mMessages.SwapElements(mCurrentTaskMessageQueue);
EnsureNextIterationLocked();
@ -1787,9 +1787,9 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
// it to process those messages. Don't do this if we're in a forced
// shutdown or it's a non-realtime graph that has already terminated
// processing.
if (mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP &&
if (LifecycleStateRef() == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP &&
mRealtime && !mForceShutDown) {
mLifecycleState = LIFECYCLE_RUNNING;
LifecycleStateRef() = LIFECYCLE_RUNNING;
// Revive the MediaStreamGraph since we have more messages going to it.
// Note that we need to put messages into its queue before reviving it,
// or it might exit immediately.
@ -1808,9 +1808,9 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
// Don't start the thread for a non-realtime graph until it has been
// explicitly started by StartNonRealtimeProcessing.
if (mLifecycleState == LIFECYCLE_THREAD_NOT_STARTED &&
if (LifecycleStateRef() == LIFECYCLE_THREAD_NOT_STARTED &&
(mRealtime || mNonRealtimeProcessing)) {
mLifecycleState = LIFECYCLE_RUNNING;
LifecycleStateRef() = LIFECYCLE_RUNNING;
// Start the thread now. We couldn't start it earlier because
// the graph might exit immediately on finding it has no streams. The
// first message for a new graph must create a stream.
@ -1835,7 +1835,7 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
}
if ((mForceShutDown || !mRealtime) &&
mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) {
LifecycleStateRef() == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) {
// Defer calls to RunDuringShutdown() to happen while mMonitor is not held.
for (uint32_t i = 0; i < mBackMessageQueue.Length(); ++i) {
MessageBlock& mb = mBackMessageQueue[i];
@ -1845,12 +1845,12 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
MOZ_ASSERT(mCurrentTaskMessageQueue.IsEmpty());
// Stop MediaStreamGraph threads. Do not clear gGraph since
// we have outstanding DOM objects that may need it.
mLifecycleState = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
LifecycleStateRef() = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphShutDownRunnable(this);
mAbstractMainThread->Dispatch(event.forget());
}
mDetectedNotRunning = mLifecycleState > LIFECYCLE_RUNNING;
mDetectedNotRunning = LifecycleStateRef() > LIFECYCLE_RUNNING;
}
// Make sure we get a new current time in the next event loop task
@ -1865,7 +1865,7 @@ MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
#ifdef DEBUG
mCanRunMessagesSynchronously = mDetectedNotRunning &&
mLifecycleState >= LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
LifecycleStateRef() >= LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
#endif
for (uint32_t i = 0; i < runnables.Length(); ++i) {
@ -1908,7 +1908,7 @@ MediaStreamGraphImpl::AppendMessage(UniquePtr<ControlMessage> aMessage)
"Stream already destroyed");
if (mDetectedNotRunning &&
mLifecycleState > LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) {
LifecycleStateRef() > LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP) {
// The graph control loop is not running and main thread cleanup has
// happened. From now on we can't append messages to mCurrentTaskMessageQueue,
// because that will never be processed again, so just RunDuringShutdown
@ -1924,7 +1924,7 @@ MediaStreamGraphImpl::AppendMessage(UniquePtr<ControlMessage> aMessage)
mCanRunMessagesSynchronously = true;
#endif
if (IsEmpty() &&
mLifecycleState >= LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION) {
LifecycleStateRef() >= LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION) {
// Find the graph in the hash table and remove it.
for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
@ -3223,12 +3223,12 @@ SourceMediaStream::HasPendingAudioTrack()
bool
SourceMediaStream::OpenNewAudioCallbackDriver(AudioDataListener * aListener)
{
MOZ_ASSERT(GraphImpl()->mLifecycleState ==
MediaStreamGraphImpl::LifecycleState::LIFECYCLE_RUNNING);
AudioCallbackDriver* nextDriver = new AudioCallbackDriver(GraphImpl());
nextDriver->SetInputListener(aListener);
{
MonitorAutoLock lock(GraphImpl()->GetMonitor());
MOZ_ASSERT(GraphImpl()->LifecycleStateRef() ==
MediaStreamGraphImpl::LifecycleState::LIFECYCLE_RUNNING);
GraphImpl()->CurrentDriver()->SwitchAtNextIteration(nextDriver);
}
@ -3669,6 +3669,7 @@ MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
// Start the graph, but don't produce anything
graph->StartNonRealtimeProcessing(0);
}
graph->ForceShutDown(nullptr);
}
@ -3680,10 +3681,13 @@ MediaStreamGraphImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize)
{
MOZ_ASSERT(NS_IsMainThread());
if (mLifecycleState >= LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN) {
// Shutting down, nothing to report.
FinishCollectReports(aHandleReport, aData, nsTArray<AudioNodeSizes>());
return NS_OK;
{
MonitorAutoLock mon(mMonitor);
if (LifecycleStateRef() >= LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN) {
// Shutting down, nothing to report.
FinishCollectReports(aHandleReport, aData, nsTArray<AudioNodeSizes>());
return NS_OK;
}
}
class Message final : public ControlMessage {

Просмотреть файл

@ -200,8 +200,7 @@ public:
bool Running() const
{
mMonitor.AssertCurrentThreadOwns();
return mLifecycleState == LIFECYCLE_RUNNING;
return LifecycleStateRef() == LIFECYCLE_RUNNING;
}
/* This is the end of the current iteration, that is, the current time of the
@ -730,6 +729,24 @@ public:
* we're about to shutdown) in mMonitor. mMonitor must be held when accessed.
*/
LifecycleState mLifecycleState;
LifecycleState& LifecycleStateRef()
{
#if DEBUG
if (!mDetectedNotRunning) {
mMonitor.AssertCurrentThreadOwns();
}
#endif
return mLifecycleState;
}
const LifecycleState& LifecycleStateRef() const
{
#if DEBUG
if (!mDetectedNotRunning) {
mMonitor.AssertCurrentThreadOwns();
}
#endif
return mLifecycleState;
}
/**
* The graph should stop processing at or after this time.
* Only set on main thread. Read on both main and MSG thread.