Bug 1110938 - Add timeout for CPOWs (default to 0) (r=dvander)
This commit is contained in:
@@ -1849,3 +1849,6 @@ pref("extensions.interposition.enabled", true);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
pref("browser.defaultbrowser.notificationbar", false);
|
pref("browser.defaultbrowser.notificationbar", false);
|
||||||
|
|
||||||
|
// How many milliseconds to wait for a CPOW response from the child process.
|
||||||
|
pref("dom.ipc.cpow.timeout", 0);
|
||||||
|
|||||||
@@ -2011,6 +2011,9 @@ ContentParent::ContentParent(mozIApplication* aApp,
|
|||||||
true /* Send registered chrome */);
|
true /* Send registered chrome */);
|
||||||
|
|
||||||
ContentProcessManager::GetSingleton()->AddContentProcess(this);
|
ContentProcessManager::GetSingleton()->AddContentProcess(this);
|
||||||
|
|
||||||
|
// Set a reply timeout for CPOWs.
|
||||||
|
SetReplyTimeoutMs(Preferences::GetInt("dom.ipc.cpow.timeout", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_NUWA_PROCESS
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
|||||||
@@ -571,6 +571,7 @@ PluginModuleChromeParent::ShouldContinueFromReplyTimeout()
|
|||||||
FinishHangUI();
|
FinishHangUI();
|
||||||
#endif // XP_WIN
|
#endif // XP_WIN
|
||||||
TerminateChildProcess(MessageLoop::current());
|
TerminateChildProcess(MessageLoop::current());
|
||||||
|
GetIPCChannel()->CloseWithTimeout();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -292,6 +292,8 @@ MessageChannel::MessageChannel(MessageListener *aListener)
|
|||||||
mDispatchingSyncMessage(false),
|
mDispatchingSyncMessage(false),
|
||||||
mDispatchingSyncMessagePriority(0),
|
mDispatchingSyncMessagePriority(0),
|
||||||
mCurrentTransaction(0),
|
mCurrentTransaction(0),
|
||||||
|
mTimedOutMessageSeqno(0),
|
||||||
|
mRecvdErrors(0),
|
||||||
mRemoteStackDepthGuess(false),
|
mRemoteStackDepthGuess(false),
|
||||||
mSawInterruptOutMsg(false),
|
mSawInterruptOutMsg(false),
|
||||||
mAbortOnError(false),
|
mAbortOnError(false),
|
||||||
@@ -611,8 +613,30 @@ MessageChannel::OnMessageReceivedFromLink(const Message& aMsg)
|
|||||||
|
|
||||||
// Regardless of the Interrupt stack, if we're awaiting a sync reply,
|
// Regardless of the Interrupt stack, if we're awaiting a sync reply,
|
||||||
// we know that it needs to be immediately handled to unblock us.
|
// we know that it needs to be immediately handled to unblock us.
|
||||||
if (AwaitingSyncReply() && aMsg.is_sync() && aMsg.is_reply()) {
|
if (aMsg.is_sync() && aMsg.is_reply()) {
|
||||||
|
if (aMsg.seqno() == mTimedOutMessageSeqno) {
|
||||||
|
// Drop the message, but allow future sync messages to be sent.
|
||||||
|
mTimedOutMessageSeqno = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(AwaitingSyncReply());
|
||||||
MOZ_ASSERT(!mRecvd);
|
MOZ_ASSERT(!mRecvd);
|
||||||
|
|
||||||
|
// Rather than storing errors in mRecvd, we mark them in
|
||||||
|
// mRecvdErrors. We need a counter because multiple replies can arrive
|
||||||
|
// when a timeout happens, as in the following example. Imagine the
|
||||||
|
// child is running slowly. The parent sends a sync message P1. It times
|
||||||
|
// out. The child eventually sends a sync message C1. While waiting for
|
||||||
|
// the C1 response, the child dispatches P1. In doing so, it sends sync
|
||||||
|
// message C2. At that point, it's valid for the parent to send error
|
||||||
|
// responses for both C1 and C2.
|
||||||
|
if (aMsg.is_reply_error()) {
|
||||||
|
mRecvdErrors++;
|
||||||
|
NotifyWorkerThread();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mRecvd = new Message(aMsg);
|
mRecvd = new Message(aMsg);
|
||||||
NotifyWorkerThread();
|
NotifyWorkerThread();
|
||||||
return;
|
return;
|
||||||
@@ -698,6 +722,14 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||||||
|
|
||||||
MonitorAutoLock lock(*mMonitor);
|
MonitorAutoLock lock(*mMonitor);
|
||||||
|
|
||||||
|
if (mTimedOutMessageSeqno) {
|
||||||
|
// Don't bother sending another sync message if a previous one timed out
|
||||||
|
// and we haven't received a reply for it. Once the original timed-out
|
||||||
|
// message receives a reply, we'll be able to send more sync messages
|
||||||
|
// again.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
IPC_ASSERT(aMsg->is_sync(), "can only Send() sync messages here");
|
IPC_ASSERT(aMsg->is_sync(), "can only Send() sync messages here");
|
||||||
IPC_ASSERT(aMsg->priority() >= DispatchingSyncMessagePriority(),
|
IPC_ASSERT(aMsg->priority() >= DispatchingSyncMessagePriority(),
|
||||||
"can't send sync message of a lesser priority than what's being dispatched");
|
"can't send sync message of a lesser priority than what's being dispatched");
|
||||||
@@ -713,12 +745,12 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||||||
|
|
||||||
msg->set_seqno(NextSeqno());
|
msg->set_seqno(NextSeqno());
|
||||||
|
|
||||||
DebugOnly<int32_t> replySeqno = msg->seqno();
|
int32_t seqno = msg->seqno();
|
||||||
DebugOnly<msgid_t> replyType = msg->type() + 1;
|
DebugOnly<msgid_t> replyType = msg->type() + 1;
|
||||||
|
|
||||||
AutoSetValue<bool> replies(mAwaitingSyncReply, true);
|
AutoSetValue<bool> replies(mAwaitingSyncReply, true);
|
||||||
AutoSetValue<int> prio(mAwaitingSyncReplyPriority, msg->priority());
|
AutoSetValue<int> prio(mAwaitingSyncReplyPriority, msg->priority());
|
||||||
AutoEnterTransaction transact(this, msg->seqno());
|
AutoEnterTransaction transact(this, seqno);
|
||||||
|
|
||||||
int32_t transaction = mCurrentTransaction;
|
int32_t transaction = mCurrentTransaction;
|
||||||
msg->set_transaction_id(transaction);
|
msg->set_transaction_id(transaction);
|
||||||
@@ -750,16 +782,16 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See if we've received a reply.
|
// See if we've received a reply.
|
||||||
|
if (mRecvdErrors) {
|
||||||
|
mRecvdErrors--;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (mRecvd) {
|
if (mRecvd) {
|
||||||
MOZ_ASSERT(mRecvd->is_reply(), "expected reply");
|
MOZ_ASSERT(mRecvd->is_reply(), "expected reply");
|
||||||
|
MOZ_ASSERT(!mRecvd->is_reply_error());
|
||||||
if (mRecvd->is_reply_error()) {
|
|
||||||
mRecvd = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(mRecvd->type() == replyType, "wrong reply type");
|
MOZ_ASSERT(mRecvd->type() == replyType, "wrong reply type");
|
||||||
MOZ_ASSERT(mRecvd->seqno() == replySeqno);
|
MOZ_ASSERT(mRecvd->seqno() == seqno);
|
||||||
MOZ_ASSERT(mRecvd->is_sync());
|
MOZ_ASSERT(mRecvd->is_sync());
|
||||||
|
|
||||||
*aReply = Move(*mRecvd);
|
*aReply = Move(*mRecvd);
|
||||||
@@ -767,6 +799,8 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mTimedOutMessageSeqno);
|
||||||
|
|
||||||
bool maybeTimedOut = !WaitForSyncNotify();
|
bool maybeTimedOut = !WaitForSyncNotify();
|
||||||
|
|
||||||
if (!Connected()) {
|
if (!Connected()) {
|
||||||
@@ -774,8 +808,13 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maybeTimedOut && !ShouldContinueFromTimeout())
|
// We only time out a message if it initiated a new transaction (i.e.,
|
||||||
|
// if neither side has any other message Sends on the stack).
|
||||||
|
bool canTimeOut = transaction == seqno;
|
||||||
|
if (maybeTimedOut && canTimeOut && !ShouldContinueFromTimeout()) {
|
||||||
|
mTimedOutMessageSeqno = seqno;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1089,7 +1128,14 @@ MessageChannel::DispatchSyncMessage(const Message& aMsg)
|
|||||||
bool& blockingVar = ShouldBlockScripts() ? gParentIsBlocked : dummy;
|
bool& blockingVar = ShouldBlockScripts() ? gParentIsBlocked : dummy;
|
||||||
|
|
||||||
Result rv;
|
Result rv;
|
||||||
{
|
if (mTimedOutMessageSeqno) {
|
||||||
|
// If the other side sends a message in response to one of our messages
|
||||||
|
// that we've timed out, then we reply with an error.
|
||||||
|
//
|
||||||
|
// We even reject messages that were sent before the other side even got
|
||||||
|
// to our timed out message.
|
||||||
|
rv = MsgNotAllowed;
|
||||||
|
} else {
|
||||||
AutoSetValue<bool> blocked(blockingVar, true);
|
AutoSetValue<bool> blocked(blockingVar, true);
|
||||||
AutoSetValue<bool> sync(mDispatchingSyncMessage, true);
|
AutoSetValue<bool> sync(mDispatchingSyncMessage, true);
|
||||||
AutoSetValue<int> prioSet(mDispatchingSyncMessagePriority, prio);
|
AutoSetValue<int> prioSet(mDispatchingSyncMessagePriority, prio);
|
||||||
@@ -1104,6 +1150,7 @@ MessageChannel::DispatchSyncMessage(const Message& aMsg)
|
|||||||
reply->set_reply_error();
|
reply->set_reply_error();
|
||||||
}
|
}
|
||||||
reply->set_seqno(aMsg.seqno());
|
reply->set_seqno(aMsg.seqno());
|
||||||
|
reply->set_transaction_id(aMsg.transaction_id());
|
||||||
|
|
||||||
MonitorAutoLock lock(*mMonitor);
|
MonitorAutoLock lock(*mMonitor);
|
||||||
if (ChannelConnected == mChannelState) {
|
if (ChannelConnected == mChannelState) {
|
||||||
@@ -1361,21 +1408,6 @@ MessageChannel::ShouldContinueFromTimeout()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cont) {
|
|
||||||
// NB: there's a sublety here. If parents were allowed to send sync
|
|
||||||
// messages to children, then it would be possible for this
|
|
||||||
// synchronous close-on-timeout to race with async |OnMessageReceived|
|
|
||||||
// tasks arriving from the child, posted to the worker thread's event
|
|
||||||
// loop. This would complicate cleanup of the *Channel. But since
|
|
||||||
// IPDL forbids this (and since it doesn't support children timing out
|
|
||||||
// on parents), the parent can only block on interrupt messages to the child,
|
|
||||||
// and in that case arriving async messages are enqueued to the interrupt
|
|
||||||
// channel's special queue. They're then ignored because the channel
|
|
||||||
// state changes to ChannelTimeout (i.e. !Connected).
|
|
||||||
SynchronouslyClose();
|
|
||||||
mChannelState = ChannelTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cont;
|
return cont;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1618,6 +1650,19 @@ MessageChannel::CloseWithError()
|
|||||||
PostErrorNotifyTask();
|
PostErrorNotifyTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MessageChannel::CloseWithTimeout()
|
||||||
|
{
|
||||||
|
AssertWorkerThread();
|
||||||
|
|
||||||
|
MonitorAutoLock lock(*mMonitor);
|
||||||
|
if (ChannelConnected != mChannelState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SynchronouslyClose();
|
||||||
|
mChannelState = ChannelTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MessageChannel::BlockScripts()
|
MessageChannel::BlockScripts()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ class MessageChannel : HasResultCodes
|
|||||||
// for process links only, not thread links.
|
// for process links only, not thread links.
|
||||||
void CloseWithError();
|
void CloseWithError();
|
||||||
|
|
||||||
|
void CloseWithTimeout();
|
||||||
|
|
||||||
void SetAbortOnError(bool abort)
|
void SetAbortOnError(bool abort)
|
||||||
{
|
{
|
||||||
mAbortOnError = true;
|
mAbortOnError = true;
|
||||||
@@ -518,10 +520,29 @@ class MessageChannel : HasResultCodes
|
|||||||
int32_t mOldTransaction;
|
int32_t mOldTransaction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If a sync message times out, we store its sequence number here. Any
|
||||||
|
// future sync messages will fail immediately. Once the reply for original
|
||||||
|
// sync message is received, we allow sync messages again.
|
||||||
|
//
|
||||||
|
// When a message times out, nothing is done to inform the other side. The
|
||||||
|
// other side will eventually dispatch the message and send a reply. Our
|
||||||
|
// side is responsible for replying to all sync messages sent by the other
|
||||||
|
// side when it dispatches the timed out message. The response is always an
|
||||||
|
// error.
|
||||||
|
//
|
||||||
|
// A message is only timed out if it initiated a transaction. This avoids
|
||||||
|
// hitting a lot of corner cases with message nesting that we don't really
|
||||||
|
// care about.
|
||||||
|
int32_t mTimedOutMessageSeqno;
|
||||||
|
|
||||||
// If waiting for the reply to a sync out-message, it will be saved here
|
// If waiting for the reply to a sync out-message, it will be saved here
|
||||||
// on the I/O thread and then read and cleared by the worker thread.
|
// on the I/O thread and then read and cleared by the worker thread.
|
||||||
nsAutoPtr<Message> mRecvd;
|
nsAutoPtr<Message> mRecvd;
|
||||||
|
|
||||||
|
// If a sync message reply that is an error arrives, we increment this
|
||||||
|
// counter rather than storing it in mRecvd.
|
||||||
|
size_t mRecvdErrors;
|
||||||
|
|
||||||
// Queue of all incoming messages, except for replies to sync and urgent
|
// Queue of all incoming messages, except for replies to sync and urgent
|
||||||
// messages, which are delivered directly to mRecvd, and any pending urgent
|
// messages, which are delivered directly to mRecvd, and any pending urgent
|
||||||
// incall, which is stored in mPendingUrgentRequest.
|
// incall, which is stored in mPendingUrgentRequest.
|
||||||
|
|||||||
24
ipc/ipdl/test/cxx/PTestUrgentHangs.ipdl
Normal file
24
ipc/ipdl/test/cxx/PTestUrgentHangs.ipdl
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace mozilla {
|
||||||
|
namespace _ipdltest {
|
||||||
|
|
||||||
|
prio(normal upto high) sync protocol PTestUrgentHangs
|
||||||
|
{
|
||||||
|
parent:
|
||||||
|
prio(high) sync Test1_2();
|
||||||
|
|
||||||
|
prio(high) sync TestInner();
|
||||||
|
|
||||||
|
child:
|
||||||
|
prio(high) sync Test1_1();
|
||||||
|
prio(high) sync Test1_3();
|
||||||
|
|
||||||
|
prio(high) sync Test2();
|
||||||
|
|
||||||
|
prio(high) sync Test3();
|
||||||
|
|
||||||
|
async Test4();
|
||||||
|
prio(high) sync Test4_1();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace _ipdltest
|
||||||
|
} // namespace mozilla
|
||||||
170
ipc/ipdl/test/cxx/TestUrgentHangs.cpp
Normal file
170
ipc/ipdl/test/cxx/TestUrgentHangs.cpp
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: sw=4 ts=4 et :
|
||||||
|
*/
|
||||||
|
#include "TestUrgentHangs.h"
|
||||||
|
|
||||||
|
#include "IPDLUnitTests.h" // fail etc.
|
||||||
|
#if defined(OS_POSIX)
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct RunnableMethodTraits<mozilla::_ipdltest::TestUrgentHangsParent>
|
||||||
|
{
|
||||||
|
static void RetainCallee(mozilla::_ipdltest::TestUrgentHangsParent* obj) { }
|
||||||
|
static void ReleaseCallee(mozilla::_ipdltest::TestUrgentHangsParent* obj) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace _ipdltest {
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// parent
|
||||||
|
|
||||||
|
TestUrgentHangsParent::TestUrgentHangsParent()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(TestUrgentHangsParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestUrgentHangsParent::~TestUrgentHangsParent()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(TestUrgentHangsParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TestUrgentHangsParent::Main()
|
||||||
|
{
|
||||||
|
SetReplyTimeoutMs(1000);
|
||||||
|
|
||||||
|
// Should succeed despite the nested sleep call because the content process
|
||||||
|
// responded to the transaction.
|
||||||
|
if (!SendTest1_1())
|
||||||
|
fail("sending Test1_1");
|
||||||
|
|
||||||
|
// Fails with a timeout.
|
||||||
|
if (SendTest2())
|
||||||
|
fail("sending Test2");
|
||||||
|
|
||||||
|
// Also fails since we haven't gotten a response for Test2 yet.
|
||||||
|
if (SendTest3())
|
||||||
|
fail("sending Test3");
|
||||||
|
|
||||||
|
// Do a second round of testing once the reply to Test2 comes back.
|
||||||
|
MessageLoop::current()->PostDelayedTask(
|
||||||
|
FROM_HERE,
|
||||||
|
NewRunnableMethod(this, &TestUrgentHangsParent::FinishTesting),
|
||||||
|
3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TestUrgentHangsParent::FinishTesting()
|
||||||
|
{
|
||||||
|
// Send an async message that waits 2 seconds and then sends a sync message
|
||||||
|
// (which should be processed).
|
||||||
|
if (!SendTest4())
|
||||||
|
fail("sending Test4");
|
||||||
|
|
||||||
|
// Send a sync message that will time out because the child is waiting
|
||||||
|
// inside RecvTest4.
|
||||||
|
if (SendTest4_1())
|
||||||
|
fail("sending Test4_1");
|
||||||
|
|
||||||
|
// Close the channel after the child finishes its work in RecvTest4.
|
||||||
|
MessageLoop::current()->PostDelayedTask(
|
||||||
|
FROM_HERE,
|
||||||
|
NewRunnableMethod(this, &TestUrgentHangsParent::Close),
|
||||||
|
3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TestUrgentHangsParent::RecvTest1_2()
|
||||||
|
{
|
||||||
|
if (!SendTest1_3())
|
||||||
|
fail("sending Test1_3");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TestUrgentHangsParent::RecvTestInner()
|
||||||
|
{
|
||||||
|
fail("TestInner should never be dispatched");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// child
|
||||||
|
|
||||||
|
bool
|
||||||
|
TestUrgentHangsChild::RecvTest1_1()
|
||||||
|
{
|
||||||
|
if (!SendTest1_2())
|
||||||
|
fail("sending Test1_2");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TestUrgentHangsChild::RecvTest1_3()
|
||||||
|
{
|
||||||
|
sleep(2);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TestUrgentHangsChild::RecvTest2()
|
||||||
|
{
|
||||||
|
sleep(2);
|
||||||
|
|
||||||
|
// Should fail because of the timeout.
|
||||||
|
if (SendTestInner())
|
||||||
|
fail("sending TestInner");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TestUrgentHangsChild::RecvTest3()
|
||||||
|
{
|
||||||
|
fail("RecvTest3 should never be called");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TestUrgentHangsChild::RecvTest4()
|
||||||
|
{
|
||||||
|
sleep(2);
|
||||||
|
|
||||||
|
// This should fail because Test4_1 timed out and hasn't gotten a response
|
||||||
|
// yet.
|
||||||
|
if (SendTestInner())
|
||||||
|
fail("sending TestInner");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TestUrgentHangsChild::RecvTest4_1()
|
||||||
|
{
|
||||||
|
// This should fail because Test4_1 timed out and hasn't gotten a response
|
||||||
|
// yet.
|
||||||
|
if (SendTestInner())
|
||||||
|
fail("sending TestInner");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestUrgentHangsChild::TestUrgentHangsChild()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(TestUrgentHangsChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestUrgentHangsChild::~TestUrgentHangsChild()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(TestUrgentHangsChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace _ipdltest
|
||||||
|
} // namespace mozilla
|
||||||
66
ipc/ipdl/test/cxx/TestUrgentHangs.h
Normal file
66
ipc/ipdl/test/cxx/TestUrgentHangs.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#ifndef mozilla__ipdltest_TestUrgentHangs_h
|
||||||
|
#define mozilla__ipdltest_TestUrgentHangs_h 1
|
||||||
|
|
||||||
|
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||||
|
|
||||||
|
#include "mozilla/_ipdltest/PTestUrgentHangsParent.h"
|
||||||
|
#include "mozilla/_ipdltest/PTestUrgentHangsChild.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace _ipdltest {
|
||||||
|
|
||||||
|
|
||||||
|
class TestUrgentHangsParent :
|
||||||
|
public PTestUrgentHangsParent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestUrgentHangsParent();
|
||||||
|
virtual ~TestUrgentHangsParent();
|
||||||
|
|
||||||
|
static bool RunTestInProcesses() { return true; }
|
||||||
|
static bool RunTestInThreads() { return false; }
|
||||||
|
|
||||||
|
void Main();
|
||||||
|
void FinishTesting();
|
||||||
|
|
||||||
|
bool RecvTest1_2();
|
||||||
|
bool RecvTestInner();
|
||||||
|
|
||||||
|
bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
passed("ok");
|
||||||
|
QuitParent();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class TestUrgentHangsChild :
|
||||||
|
public PTestUrgentHangsChild
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestUrgentHangsChild();
|
||||||
|
virtual ~TestUrgentHangsChild();
|
||||||
|
|
||||||
|
bool RecvTest1_1();
|
||||||
|
bool RecvTest1_3();
|
||||||
|
bool RecvTest2();
|
||||||
|
bool RecvTest3();
|
||||||
|
bool RecvTest4();
|
||||||
|
bool RecvTest4_1();
|
||||||
|
|
||||||
|
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
QuitChild();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace _ipdltest
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ifndef mozilla__ipdltest_TestUrgentHangs_h
|
||||||
@@ -46,6 +46,7 @@ SOURCES += [
|
|||||||
'TestSyncHang.cpp',
|
'TestSyncHang.cpp',
|
||||||
'TestSyncWakeup.cpp',
|
'TestSyncWakeup.cpp',
|
||||||
'TestUrgency.cpp',
|
'TestUrgency.cpp',
|
||||||
|
'TestUrgentHangs.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['OS_ARCH'] == 'Linux':
|
if CONFIG['OS_ARCH'] == 'Linux':
|
||||||
@@ -120,6 +121,7 @@ IPDL_SOURCES += [
|
|||||||
'PTestSyncWakeup.ipdl',
|
'PTestSyncWakeup.ipdl',
|
||||||
'PTestSysVShmem.ipdl',
|
'PTestSysVShmem.ipdl',
|
||||||
'PTestUrgency.ipdl',
|
'PTestUrgency.ipdl',
|
||||||
|
'PTestUrgentHangs.ipdl',
|
||||||
]
|
]
|
||||||
|
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|||||||
@@ -809,7 +809,7 @@ class B2GOptions(MochitestOptions):
|
|||||||
defaults["testPath"] = ""
|
defaults["testPath"] = ""
|
||||||
defaults["extensionsToExclude"] = ["specialpowers"]
|
defaults["extensionsToExclude"] = ["specialpowers"]
|
||||||
# See dependencies of bug 1038943.
|
# See dependencies of bug 1038943.
|
||||||
defaults["defaultLeakThreshold"] = 5308
|
defaults["defaultLeakThreshold"] = 5404
|
||||||
self.set_defaults(**defaults)
|
self.set_defaults(**defaults)
|
||||||
|
|
||||||
def verifyRemoteOptions(self, options):
|
def verifyRemoteOptions(self, options):
|
||||||
|
|||||||
Reference in New Issue
Block a user