Bug 829909 - Fix some Plugin Hang UI synchronization problems. r=bbondy

This commit is contained in:
Aaron Klotz 2013-01-17 21:22:21 -05:00
parent b8ddec986c
commit a8423a5207
4 changed files with 40 additions and 13 deletions

View File

@ -126,6 +126,8 @@ MiniShmParent::Init(MiniShmObserver* aObserver, const DWORD aTimeout,
} }
nsresult rv = SetView(view, aSectionSize, false); nsresult rv = SetView(view, aSectionSize, false);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = SetGuard(childGuard, aTimeout);
NS_ENSURE_SUCCESS(rv, rv);
MiniShmInit* initStruct = nullptr; MiniShmInit* initStruct = nullptr;
rv = GetWritePtrInternal(initStruct); rv = GetWritePtrInternal(initStruct);
@ -174,12 +176,9 @@ MiniShmParent::GetCookie(std::wstring& cookie)
nsresult nsresult
MiniShmParent::Send() MiniShmParent::Send()
{ {
if (!mChildEvent || !mChildGuard) { if (!mChildEvent) {
return NS_ERROR_NOT_INITIALIZED; return NS_ERROR_NOT_INITIALIZED;
} }
if (::WaitForSingleObject(mChildGuard, mTimeout) != WAIT_OBJECT_0) {
return NS_ERROR_FAILURE;
}
if (!::SetEvent(mChildEvent)) { if (!::SetEvent(mChildEvent)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

View File

@ -322,6 +322,12 @@ PluginHangUIParent::OnMiniShmEvent(MiniShmBase *aMiniShmObj)
NS_ASSERTION(NS_SUCCEEDED(rv), NS_ASSERTION(NS_SUCCEEDED(rv),
"Couldn't obtain read pointer OnMiniShmEvent"); "Couldn't obtain read pointer OnMiniShmEvent");
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
// The child process has returned a response so we shouldn't worry about
// its state anymore.
if (::UnregisterWaitEx(mRegWait, NULL)) {
mRegWait = NULL;
}
RecvUserResponse(response->mResponseBits); RecvUserResponse(response->mResponseBits);
} }
} }

View File

@ -121,17 +121,21 @@ public:
* @return NS_OK if and only if aPtr was successfully obtained. * @return NS_OK if and only if aPtr was successfully obtained.
* NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm. * NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm.
* NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection. * NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection.
* NS_ERROR_NOT_AVAILABLE if the memory is not safe to write.
*/ */
template<typename T> nsresult template<typename T> nsresult
GetWritePtr(T*& aPtr) GetWritePtr(T*& aPtr)
{ {
if (!mWriteHeader) { if (!mWriteHeader || !mGuard) {
return NS_ERROR_NOT_INITIALIZED; return NS_ERROR_NOT_INITIALIZED;
} }
if (sizeof(T) > mPayloadMaxLen || if (sizeof(T) > mPayloadMaxLen ||
T::identifier <= RESERVED_CODE_LAST) { T::identifier <= RESERVED_CODE_LAST) {
return NS_ERROR_ILLEGAL_VALUE; return NS_ERROR_ILLEGAL_VALUE;
} }
if (::WaitForSingleObject(mGuard, mTimeout) != WAIT_OBJECT_0) {
return NS_ERROR_NOT_AVAILABLE;
}
mWriteHeader->mId = T::identifier; mWriteHeader->mId = T::identifier;
mWriteHeader->mPayloadLen = sizeof(T); mWriteHeader->mPayloadLen = sizeof(T);
aPtr = reinterpret_cast<T*>(mWriteHeader + 1); aPtr = reinterpret_cast<T*>(mWriteHeader + 1);
@ -219,7 +223,9 @@ protected:
: mObserver(nullptr), : mObserver(nullptr),
mWriteHeader(nullptr), mWriteHeader(nullptr),
mReadHeader(nullptr), mReadHeader(nullptr),
mPayloadMaxLen(0) mPayloadMaxLen(0),
mGuard(NULL),
mTimeout(INFINITE)
{ {
} }
virtual ~MiniShmBase() virtual ~MiniShmBase()
@ -261,6 +267,17 @@ protected:
return NS_OK; return NS_OK;
} }
nsresult
SetGuard(HANDLE aGuard, DWORD aTimeout)
{
if (!aGuard || !aTimeout) {
return NS_ERROR_ILLEGAL_VALUE;
}
mGuard = aGuard;
mTimeout = aTimeout;
return NS_OK;
}
inline void inline void
SetObserver(MiniShmObserver *aObserver) { mObserver = aObserver; } SetObserver(MiniShmObserver *aObserver) { mObserver = aObserver; }
@ -304,6 +321,8 @@ private:
MiniShmHeader* mWriteHeader; MiniShmHeader* mWriteHeader;
MiniShmHeader* mReadHeader; MiniShmHeader* mReadHeader;
unsigned int mPayloadMaxLen; unsigned int mPayloadMaxLen;
HANDLE mGuard;
DWORD mTimeout;
DISALLOW_COPY_AND_ASSIGN(MiniShmBase); DISALLOW_COPY_AND_ASSIGN(MiniShmBase);
}; };

View File

@ -28,12 +28,14 @@ MiniShmChild::~MiniShmChild()
if (mRegWait) { if (mRegWait) {
::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE); ::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE);
} }
if (mParentGuard) {
// Try to avoid shutting down while the parent's event handler is running.
::WaitForSingleObject(mParentGuard, mTimeout);
::CloseHandle(mParentGuard);
}
if (mParentEvent) { if (mParentEvent) {
::CloseHandle(mParentEvent); ::CloseHandle(mParentEvent);
} }
if (mParentGuard) {
::CloseHandle(mParentGuard);
}
if (mChildEvent) { if (mChildEvent) {
::CloseHandle(mChildEvent); ::CloseHandle(mChildEvent);
} }
@ -95,6 +97,10 @@ MiniShmChild::Init(MiniShmObserver* aObserver, const std::wstring& aCookie,
!initStruct->mChildEvent || !initStruct->mChildGuard) { !initStruct->mChildEvent || !initStruct->mChildGuard) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
rv = SetGuard(initStruct->mParentGuard, aTimeout);
if (NS_FAILED(rv)) {
return rv;
}
if (!::RegisterWaitForSingleObject(&mRegWait, if (!::RegisterWaitForSingleObject(&mRegWait,
initStruct->mChildEvent, initStruct->mChildEvent,
&SOnEvent, &SOnEvent,
@ -146,12 +152,9 @@ MiniShmChild::Init(MiniShmObserver* aObserver, const std::wstring& aCookie,
nsresult nsresult
MiniShmChild::Send() MiniShmChild::Send()
{ {
if (!mParentEvent || !mParentGuard) { if (!mParentEvent) {
return NS_ERROR_NOT_INITIALIZED; return NS_ERROR_NOT_INITIALIZED;
} }
if (::WaitForSingleObject(mParentGuard, mTimeout) != WAIT_OBJECT_0) {
return NS_ERROR_FAILURE;
}
if (!::SetEvent(mParentEvent)) { if (!::SetEvent(mParentEvent)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }