зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1322377 - frequent intermittent timeouts in TestNamedPipeService - there was a race between notifying the monitor and waiting for it, so instead of a monitor use an event, r=bagder
MozReview-Commit-ID: 6xgSH6shSm6 --HG-- extra : rebase_source : 36554d14857eb441b52f386a2984d02bd683cdd4
This commit is contained in:
Родитель
458019a9d8
Коммит
e2074c41cd
|
@ -18,6 +18,41 @@
|
|||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Unlike a monitor, an event allows a thread to wait on another thread
|
||||
* completing an action without regard to ordering of the wait and the notify.
|
||||
*/
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
explicit Event(const char* aName)
|
||||
: mMonitor(aName) { }
|
||||
|
||||
~Event() = default;
|
||||
|
||||
void Set() {
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
MOZ_ASSERT(!mSignaled);
|
||||
mSignaled = true;
|
||||
mMonitor.Notify();
|
||||
}
|
||||
void Wait() {
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
while (!mSignaled) {
|
||||
lock.Wait();
|
||||
}
|
||||
mSignaled = false;
|
||||
}
|
||||
|
||||
private:
|
||||
Monitor mMonitor;
|
||||
bool mSignaled = false;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class nsNamedPipeDataObserver : public nsINamedPipeDataObserver
|
||||
{
|
||||
public:
|
||||
|
@ -37,7 +72,7 @@ private:
|
|||
HANDLE mPipe;
|
||||
OVERLAPPED mOverlapped;
|
||||
Atomic<uint32_t> mBytesTransferred;
|
||||
Monitor mMonitor;
|
||||
Event mEvent;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsNamedPipeDataObserver, nsINamedPipeDataObserver)
|
||||
|
@ -46,7 +81,7 @@ nsNamedPipeDataObserver::nsNamedPipeDataObserver(HANDLE aPipe)
|
|||
: mPipe(aPipe)
|
||||
, mOverlapped()
|
||||
, mBytesTransferred(0)
|
||||
, mMonitor("named-pipe")
|
||||
, mEvent("named-pipe")
|
||||
{
|
||||
mOverlapped.hEvent = CreateEventA(nullptr, TRUE, TRUE, "named-pipe");
|
||||
}
|
||||
|
@ -59,8 +94,7 @@ nsNamedPipeDataObserver::Read(void* aBuffer, uint32_t aSize)
|
|||
switch(GetLastError()) {
|
||||
case ERROR_IO_PENDING:
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mMonitor.Wait();
|
||||
mEvent.Wait();
|
||||
}
|
||||
if (!GetOverlappedResult(mPipe, &mOverlapped, &bytesRead, FALSE)) {
|
||||
ADD_FAILURE() << "GetOverlappedResult failed";
|
||||
|
@ -77,8 +111,7 @@ nsNamedPipeDataObserver::Read(void* aBuffer, uint32_t aSize)
|
|||
return -1;
|
||||
}
|
||||
} else {
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mMonitor.Wait();
|
||||
mEvent.Wait();
|
||||
|
||||
if (mBytesTransferred != bytesRead) {
|
||||
ADD_FAILURE() << "GetOverlappedResult mismatch";
|
||||
|
@ -98,8 +131,7 @@ nsNamedPipeDataObserver::Write(const void* aBuffer, uint32_t aSize)
|
|||
switch(GetLastError()) {
|
||||
case ERROR_IO_PENDING:
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mMonitor.Wait();
|
||||
mEvent.Wait();
|
||||
}
|
||||
if (!GetOverlappedResult(mPipe, &mOverlapped, &bytesWritten, FALSE)) {
|
||||
ADD_FAILURE() << "GetOverlappedResult failed";
|
||||
|
@ -116,8 +148,7 @@ nsNamedPipeDataObserver::Write(const void* aBuffer, uint32_t aSize)
|
|||
return -1;
|
||||
}
|
||||
} else {
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mMonitor.Wait();
|
||||
mEvent.Wait();
|
||||
|
||||
if (mBytesTransferred != bytesWritten) {
|
||||
ADD_FAILURE() << "GetOverlappedResult mismatch";
|
||||
|
@ -155,8 +186,7 @@ nsNamedPipeDataObserver::OnDataAvailable(uint32_t aBytesTransferred,
|
|||
}
|
||||
|
||||
mBytesTransferred += aBytesTransferred;
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mMonitor.Notify();
|
||||
mEvent.Set();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче