Backed out changeset 97c2d1419843 (bug 1423833) for assertion failures on WinWindowOcclusionTracker.cpp. CLOSED TREE

This commit is contained in:
Csoregi Natalia 2023-01-24 04:12:03 +02:00
parent 3c392b55f3
commit 507ccc820b
2 changed files with 44 additions and 68 deletions

View File

@ -18,6 +18,7 @@
#include "nsThreadUtils.h"
#include "mozilla/DataMutex.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/layers/SynchronousTask.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Logging.h"
#include "mozilla/StaticPrefs_widget.h"
@ -335,30 +336,21 @@ void WinWindowOcclusionTracker::Ensure() {
MOZ_ASSERT(NS_IsMainThread());
LOG(LogLevel::Info, "WinWindowOcclusionTracker::Ensure()");
base::Thread::Options options;
options.message_loop_type = MessageLoop::TYPE_UI;
if (sTracker) {
// Try to reuse the thread, which involves stopping and restarting it.
sTracker->mThread->Stop();
if (sTracker->mThread->StartWithOptions(options)) {
// Success!
return;
}
// Restart failed, so null out our sTracker and try again with a new
// thread. This will cause the old singleton instance to be deallocated,
// which will destroy its mThread as well.
sTracker = nullptr;
}
UniquePtr<base::Thread> thread =
MakeUnique<base::Thread>("WinWindowOcclusionCalc");
if (!thread->StartWithOptions(options)) {
return;
}
sTracker = new WinWindowOcclusionTracker(std::move(thread));
base::Thread* thread = new base::Thread("WinWindowOcclusionCalc");
base::Thread::Options options;
options.message_loop_type = MessageLoop::TYPE_UI;
if (!thread->StartWithOptions(options)) {
delete thread;
return;
}
sTracker = new WinWindowOcclusionTracker(thread);
WindowOcclusionCalculator::CreateInstance();
RefPtr<Runnable> runnable =
@ -370,46 +362,34 @@ void WinWindowOcclusionTracker::Ensure() {
/* static */
void WinWindowOcclusionTracker::ShutDown() {
if (!sTracker) {
return;
}
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sTracker);
LOG(LogLevel::Info, "WinWindowOcclusionTracker::ShutDown()");
sTracker->Destroy();
// Our thread could hang while we're waiting for it to stop.
// Since we're shutting down, that's not a critical problem.
// We set a reasonable amount of time to wait for shutdown,
// and if it succeeds within that time, we correctly stop
// our thread by nulling out the refptr, which will cause it
// to be deallocated and join the thread. If it times out,
// we do nothing, which means that the thread will not be
// joined and sTracker memory will leak.
static const TimeDuration TIMEOUT = TimeDuration::FromSeconds(2.0);
// Our shutdown task could hang. Since we're shutting down,
// that's not a critical problem. We set a reasonable amount
// of time to wait for shutdown, and if it succeeds within
// that time, we correctly stop our tracker thread. If it
// times out, we just leak the memory and proceed.
static const PRIntervalTime TIMEOUT = PR_TicksPerSecond() * 2;
layers::SynchronousTask task("WinWindowOcclusionTracker");
RefPtr<Runnable> runnable =
WrapRunnable(RefPtr<WindowOcclusionCalculator>(
WindowOcclusionCalculator::GetInstance()),
&WindowOcclusionCalculator::Shutdown);
&WindowOcclusionCalculator::Shutdown, &task);
OcclusionCalculatorLoop()->PostTask(runnable.forget());
CVStatus status;
{
MonitorAutoLock lock(sTracker->mMonitor);
// Monitor uses SleepConditionVariableSRW, which can have
// spurious wakeups which are reported as timeouts, so we
// check timestamps to ensure that we've waited as long we
// intended to.
TimeStamp timeStart = TimeStamp::NowLoRes();
do {
status = sTracker->mMonitor.Wait(TIMEOUT);
} while ((status == CVStatus::Timeout) &&
((TimeStamp::NowLoRes() - timeStart) < TIMEOUT));
nsresult rv = task.Wait(TIMEOUT);
if (rv == NS_OK) {
sTracker->mThread->Stop();
}
if (status == CVStatus::NoTimeout) {
WindowOcclusionCalculator::ClearInstance();
sTracker = nullptr;
}
WindowOcclusionCalculator::ClearInstance();
sTracker = nullptr;
}
void WinWindowOcclusionTracker::Destroy() {
@ -506,9 +486,8 @@ void WinWindowOcclusionTracker::OnWindowVisibilityChanged(nsBaseWidget* aWindow,
mSerializedTaskDispatcher->PostTaskToCalculator(runnable.forget());
}
WinWindowOcclusionTracker::WinWindowOcclusionTracker(
UniquePtr<base::Thread> aThread)
: mThread(std::move(aThread)), mMonitor("WinWindowOcclusionTracker") {
WinWindowOcclusionTracker::WinWindowOcclusionTracker(base::Thread* aThread)
: mThread(aThread) {
MOZ_ASSERT(NS_IsMainThread());
LOG(LogLevel::Info, "WinWindowOcclusionTracker::WinWindowOcclusionTracker()");
@ -527,6 +506,7 @@ WinWindowOcclusionTracker::~WinWindowOcclusionTracker() {
MOZ_ASSERT(NS_IsMainThread());
LOG(LogLevel::Info,
"WinWindowOcclusionTracker::~WinWindowOcclusionTracker()");
delete mThread;
}
// static
@ -835,8 +815,7 @@ StaticRefPtr<WinWindowOcclusionTracker::WindowOcclusionCalculator>
WinWindowOcclusionTracker::WindowOcclusionCalculator::sCalculator;
WinWindowOcclusionTracker::WindowOcclusionCalculator::
WindowOcclusionCalculator()
: mMonitor(WinWindowOcclusionTracker::Get()->mMonitor) {
WindowOcclusionCalculator() {
MOZ_ASSERT(NS_IsMainThread());
LOG(LogLevel::Info, "WindowOcclusionCalculator()");
@ -880,20 +859,19 @@ void WinWindowOcclusionTracker::WindowOcclusionCalculator::Initialize() {
#endif
}
void WinWindowOcclusionTracker::WindowOcclusionCalculator::Shutdown() {
MonitorAutoLock lock(mMonitor);
void WinWindowOcclusionTracker::WindowOcclusionCalculator::Shutdown(
layers::SynchronousTask* aTask) {
MOZ_ASSERT(IsInWinWindowOcclusionThread());
CALC_LOG(LogLevel::Info, "Shutdown()");
layers::AutoCompleteTask complete(aTask);
UnregisterEventHooks();
if (mOcclusionUpdateRunnable) {
mOcclusionUpdateRunnable->Cancel();
mOcclusionUpdateRunnable = nullptr;
}
mVirtualDesktopManager = nullptr;
mMonitor.NotifyAll();
}
void WinWindowOcclusionTracker::WindowOcclusionCalculator::

View File

@ -13,7 +13,6 @@
#include <vector>
#include "nsIWeakReferenceUtils.h"
#include "mozilla/Monitor.h"
#include "mozilla/ThreadSafeWeakPtr.h"
#include "mozilla/widget/WindowOcclusionState.h"
#include "mozilla/widget/WinEventObserver.h"
@ -29,6 +28,10 @@ class Thread;
namespace mozilla {
namespace layers {
class SynchronousTask;
}
namespace widget {
class OcclusionUpdateRunnable;
@ -86,7 +89,7 @@ class WinWindowOcclusionTracker final : public DisplayStatusListener,
friend class ::WinWindowOcclusionTrackerTest;
friend class ::WinWindowOcclusionTrackerInteractiveTest;
explicit WinWindowOcclusionTracker(UniquePtr<base::Thread> aThread);
explicit WinWindowOcclusionTracker(base::Thread* aThread);
virtual ~WinWindowOcclusionTracker();
// This class computes the occlusion state of the tracked windows.
@ -105,7 +108,7 @@ class WinWindowOcclusionTracker final : public DisplayStatusListener,
static WindowOcclusionCalculator* GetInstance() { return sCalculator; }
void Initialize();
void Shutdown();
void Shutdown(layers::SynchronousTask* aTask);
void EnableOcclusionTrackingForWindow(HWND hwnd);
void DisableOcclusionTrackingForWindow(HWND hwnd);
@ -249,10 +252,6 @@ class WinWindowOcclusionTracker final : public DisplayStatusListener,
// Used to serialize tasks related to mRootWindowHwndsOcclusionState.
RefPtr<SerializedTaskDispatcher> mSerializedTaskDispatcher;
// This is an alias to the singleton WinWindowOcclusionTracker mMonitor,
// and is used in ShutDown().
Monitor& mMonitor;
friend class OcclusionUpdateRunnable;
};
@ -291,8 +290,7 @@ class WinWindowOcclusionTracker final : public DisplayStatusListener,
static StaticRefPtr<WinWindowOcclusionTracker> sTracker;
// "WinWindowOcclusionCalc" thread.
UniquePtr<base::Thread> mThread;
Monitor mMonitor;
base::Thread* const mThread;
// Map of HWND to widget. Maintained on main thread, and used to send
// occlusion state notifications to Windows from