Bug 1049879 - Remove urgent and rpc message types and replace with message priorities (r=dvander,bent,ehsan)

This commit is contained in:
Bill McCloskey 2014-10-07 21:32:45 -07:00
Родитель 4985d0ee76
Коммит 2ab547d3ab
47 изменённых файлов: 1003 добавлений и 920 удалений

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

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1069071: IPDL changes require CLOBBER
Bug 1069071: IPDL changes require CLOBBER (second time around)

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

@ -1735,7 +1735,7 @@ public:
return cc->SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
IPC::Principal(aPrincipal), aJSONRetVal);
}
return cc->CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
return cc->SendRpcMessage(PromiseFlatString(aMessage), data, cpows,
IPC::Principal(aPrincipal), aJSONRetVal);
}

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

@ -17,7 +17,7 @@ struct RemoteVoice {
bool localService;
};
intr protocol PSpeechSynthesis
sync protocol PSpeechSynthesis
{
manager PContent;
manages PSpeechSynthesisRequest;

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

@ -9,7 +9,7 @@ include protocol PSpeechSynthesis;
namespace mozilla {
namespace dom {
intr protocol PSpeechSynthesisRequest
async protocol PSpeechSynthesisRequest
{
manager PSpeechSynthesis;

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

@ -3517,14 +3517,14 @@ ContentParent::RecvSyncMessage(const nsString& aMsg,
}
bool
ContentParent::AnswerRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals)
ContentParent::RecvRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals)
{
return nsIContentParent::AnswerRpcMessage(aMsg, aData, aCpows, aPrincipal,
aRetvals);
return nsIContentParent::RecvRpcMessage(aMsg, aData, aCpows, aPrincipal,
aRetvals);
}
bool

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

@ -563,11 +563,11 @@ private:
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals) MOZ_OVERRIDE;
virtual bool AnswerRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals) MOZ_OVERRIDE;
virtual bool RecvRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals) MOZ_OVERRIDE;
virtual bool RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,

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

@ -69,7 +69,7 @@ union MaybeNativeKeyBinding
void_t;
};
intr protocol PBrowser
prio(normal upto high) intr protocol PBrowser
{
manager PContent or PContentBridge;
@ -108,8 +108,8 @@ parent:
CpowEntry[] aCpows, Principal aPrincipal)
returns (nsString[] retval);
rpc RpcMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal)
prio(high) sync RpcMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal)
returns (nsString[] retval);
/**

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

@ -319,7 +319,7 @@ union MaybeFileDesc {
void_t;
};
intr protocol PContent
prio(normal upto high) intr protocol PContent
{
parent opens PCompositor;
parent opens PSharedBufferManager;
@ -537,7 +537,7 @@ parent:
PNecko();
rpc PScreenManager()
prio(high) sync PScreenManager()
returns (uint32_t numberOfScreens,
float systemDefaultScale,
bool success);
@ -577,8 +577,8 @@ parent:
CpowEntry[] aCpows, Principal aPrincipal)
returns (nsString[] retval);
rpc RpcMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal)
prio(high) sync RpcMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal)
returns (nsString[] retval);
ShowAlertNotification(nsString imageUrl,

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

@ -26,7 +26,7 @@ namespace dom {
* allocate the PContentBridgeChild. This protocol allows these processes to
* share PBrowsers and send messages to each other.
*/
intr protocol PContentBridge
prio(normal upto high) intr protocol PContentBridge
{
bridges PContent, PContent;

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

@ -19,7 +19,7 @@ struct Mapping {
size_t file_offset;
};
intr protocol PCrashReporter {
async protocol PCrashReporter {
manager PContent or PPluginModule or PGMP;
parent:
AnnotateCrashReport(nsCString key, nsCString data);

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

@ -22,32 +22,32 @@ struct ScreenDetails {
double contentsScaleFactor;
};
rpc protocol PScreenManager
prio(normal upto high) sync protocol PScreenManager
{
manager PContent;
parent:
rpc Refresh()
prio(high) sync Refresh()
returns (uint32_t numberOfScreens,
float systemDefaultScale,
bool success);
rpc ScreenRefresh(uint32_t aId)
prio(high) sync ScreenRefresh(uint32_t aId)
returns (ScreenDetails screen,
bool success);
rpc GetPrimaryScreen()
prio(high) sync GetPrimaryScreen()
returns (ScreenDetails screen,
bool success);
rpc ScreenForRect(int32_t aLeft,
prio(high) sync ScreenForRect(int32_t aLeft,
int32_t aTop,
int32_t aWidth,
int32_t aHeight)
returns (ScreenDetails screen,
bool success);
rpc ScreenForBrowser(PBrowser aBrowser)
prio(high) sync ScreenForBrowser(PBrowser aBrowser)
returns (ScreenDetails screen,
bool success);

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

@ -24,13 +24,13 @@ ScreenManagerParent::ScreenManagerParent(uint32_t* aNumberOfScreens,
MOZ_CRASH("Couldn't get nsIScreenManager from ScreenManagerParent.");
}
unused << AnswerRefresh(aNumberOfScreens, aSystemDefaultScale, aSuccess);
unused << RecvRefresh(aNumberOfScreens, aSystemDefaultScale, aSuccess);
}
bool
ScreenManagerParent::AnswerRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
ScreenManagerParent::RecvRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
*aSuccess = false;
@ -49,9 +49,9 @@ ScreenManagerParent::AnswerRefresh(uint32_t* aNumberOfScreens,
}
bool
ScreenManagerParent::AnswerScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess)
ScreenManagerParent::RecvScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
@ -70,8 +70,8 @@ ScreenManagerParent::AnswerScreenRefresh(const uint32_t& aId,
}
bool
ScreenManagerParent::AnswerGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess)
ScreenManagerParent::RecvGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
@ -91,12 +91,12 @@ ScreenManagerParent::AnswerGetPrimaryScreen(ScreenDetails* aRetVal,
}
bool
ScreenManagerParent::AnswerScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess)
ScreenManagerParent::RecvScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
@ -116,9 +116,9 @@ ScreenManagerParent::AnswerScreenForRect(const int32_t& aLeft,
}
bool
ScreenManagerParent::AnswerScreenForBrowser(PBrowserParent* aBrowser,
ScreenDetails* aRetVal,
bool* aSuccess)
ScreenManagerParent::RecvScreenForBrowser(PBrowserParent* aBrowser,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;

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

@ -21,29 +21,29 @@ class ScreenManagerParent : public PScreenManagerParent
bool* aSuccess);
~ScreenManagerParent() {};
virtual bool AnswerRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool AnswerScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool AnswerGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool AnswerScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool AnswerScreenForBrowser(PBrowserParent* aBrowser,
ScreenDetails* aRetVal,
bool* aSuccess);
virtual bool RecvScreenForBrowser(PBrowserParent* aBrowser,
ScreenDetails* aRetVal,
bool* aSuccess);
private:
bool ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails);

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

@ -2922,7 +2922,7 @@ TabChild::DoSendBlockingMessage(JSContext* aCx,
Principal(aPrincipal), aJSONRetVal);
}
return CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
return SendRpcMessage(PromiseFlatString(aMessage), data, cpows,
Principal(aPrincipal), aJSONRetVal);
}

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

@ -1128,11 +1128,11 @@ TabParent::RecvSyncMessage(const nsString& aMessage,
}
bool
TabParent::AnswerRpcMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal)
TabParent::RecvRpcMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal)
{
// FIXME Permission check for TabParent in Content process
nsIPrincipal* principal = aPrincipal;

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

@ -147,11 +147,11 @@ public:
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
virtual bool AnswerRpcMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
virtual bool RecvRpcMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
virtual bool RecvAsyncMessage(const nsString& aMessage,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,

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

@ -193,11 +193,11 @@ nsIContentParent::RecvSyncMessage(const nsString& aMsg,
}
bool
nsIContentParent::AnswerRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals)
nsIContentParent::RecvRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals)
{
// FIXME Permission check in Content process
nsIPrincipal* principal = aPrincipal;

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

@ -91,11 +91,11 @@ protected: // IPDL methods
const InfallibleTArray<jsipc::CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals);
virtual bool AnswerRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<jsipc::CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals);
virtual bool RecvRpcMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<jsipc::CpowEntry>& aCpows,
const IPC::Principal& aPrincipal,
InfallibleTArray<nsString>* aRetvals);
virtual bool RecvAsyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
const InfallibleTArray<jsipc::CpowEntry>& aCpows,

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

@ -53,9 +53,9 @@ class Message : public Pickle {
};
enum PriorityValue {
PRIORITY_LOW = 1,
PRIORITY_NORMAL,
PRIORITY_HIGH
PRIORITY_NORMAL = 1,
PRIORITY_HIGH = 2,
PRIORITY_URGENT = 3
};
enum MessageCompression {
@ -85,6 +85,11 @@ class Message : public Pickle {
return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK);
}
void set_priority(int prio) {
DCHECK((prio & ~PRIORITY_MASK) == 0);
header()->flags = (header()->flags & ~PRIORITY_MASK) | prio;
}
// True if this is a synchronous message.
bool is_sync() const {
return (header()->flags & SYNC_BIT) != 0;
@ -95,16 +100,6 @@ class Message : public Pickle {
return (header()->flags & INTERRUPT_BIT) != 0;
}
// True if this is an urgent message.
bool is_urgent() const {
return (header()->flags & URGENT_BIT) != 0;
}
// True if this is an RPC message.
bool is_rpc() const {
return (header()->flags & RPC_BIT) != 0;
}
// True if compression is enabled for this message.
bool compress() const {
return (header()->flags & COMPRESS_BIT) != 0;
@ -296,14 +291,6 @@ class Message : public Pickle {
header()->flags |= INTERRUPT_BIT;
}
void set_urgent() {
header()->flags |= URGENT_BIT;
}
void set_rpc() {
header()->flags |= RPC_BIT;
}
#if !defined(OS_MACOSX)
protected:
#endif
@ -319,8 +306,6 @@ class Message : public Pickle {
HAS_SENT_TIME_BIT = 0x0080,
INTERRUPT_BIT = 0x0100,
COMPRESS_BIT = 0x0200,
URGENT_BIT = 0x0400,
RPC_BIT = 0x0800
};
struct Header : Pickle::Header {

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

@ -20,6 +20,62 @@
// Undo the damage done by mozzconf.h
#undef compress
/*
* IPC design:
*
* There are three kinds of messages: async, sync, and intr. Sync and intr
* messages are blocking. Only intr and high-priority sync messages can nest.
*
* Terminology: To dispatch a message Foo is to run the RecvFoo code for
* it. This is also called "handling" the message.
*
* Sync messages have priorities while async and intr messages always have
* normal priority. The three possible priorities are normal, high, and urgent.
* The intended uses of these priorities are:
* NORMAL - most messages.
* HIGH - CPOW-related messages, which can go in either direction.
* URGENT - messages where we don't want to dispatch
* incoming CPOWs while waiting for the response.
*
* To avoid jank, the parent process is not allowed to send sync messages of
* normal priority. The parent also is not allowed to send urgent messages at
* all. When a process is waiting for a response to a sync message M0, it will
* dispatch an incoming message M if:
* 1. M has a higher priority than M0, or
* 2. if M has the same priority as M0 and we're in the child, or
* 3. if M has the same priority as M0 and it was sent by the other side
while dispatching M0 (nesting).
* The idea is that higher priority messages should take precendence, and we
* also want to allow nesting. The purpose of rule 2 is to handle a race where
* both processes send to each other simultaneously. In this case, we resolve
* the race in favor of the parent (so the child dispatches first).
*
* Sync messages satisfy the following properties:
* A. When waiting for a response to a sync message, we won't dispatch any
* messages of lower priority.
* B. Sync messages of the same priority will be dispatched roughly in the
* order they were sent. The exception is when the parent and child send
* sync messages to each other simulataneously. In this case, the parent's
* message is dispatched first. While it is dispatched, the child may send
* further nested messages, and these messages may be dispatched before the
* child's original message. We can consider ordering to be preserved here
* because we pretend that the child's original message wasn't sent until
* after the parent's message is finished being dispatched.
*
* Intr messages are blocking but not prioritized. While waiting for an intr
* response, all incoming messages are dispatched until a response is
* received. Intr messages also can be nested. When two intr messages race with
* each other, a similar scheme is used to ensure that one side wins. The
* winning side is chosen based on the message type.
*
* Intr messages differ from sync messages in that, while sending an intr
* message, we may dispatch an async message. This causes some additional
* complexity. One issue is that replies can be received out of order. It's also
* more difficult to determine whether one message is nested inside
* another. Consequently, intr handling uses mOutOfTurnReplies and
* mRemoteStackDepthGuess, which are not needed for sync messages.
*/
using namespace mozilla;
using namespace std;
@ -39,7 +95,7 @@ struct RunnableMethodTraits<mozilla::ipc::MessageChannel>
DebugAbort(__FILE__, __LINE__, #_cond,## __VA_ARGS__); \
} while (0)
static uintptr_t gDispatchingUrgentMessageCount;
static bool gParentIsBlocked;
namespace mozilla {
namespace ipc {
@ -195,9 +251,9 @@ namespace {
class MOZ_STACK_CLASS MaybeScriptBlocker {
public:
explicit MaybeScriptBlocker(MessageChannel *aChannel
explicit MaybeScriptBlocker(MessageChannel *aChannel, bool aBlock
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mBlocked(aChannel->ShouldBlockScripts())
: mBlocked(aChannel->ShouldBlockScripts() && aBlock)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (mBlocked) {
@ -227,12 +283,11 @@ MessageChannel::MessageChannel(MessageListener *aListener)
mTimeoutMs(kNoTimeout),
mInTimeoutSecondHalf(false),
mNextSeqno(0),
mPendingSyncReplies(0),
mPendingUrgentReplies(0),
mPendingRPCReplies(0),
mCurrentRPCTransaction(0),
mAwaitingSyncReply(false),
mAwaitingSyncReplyPriority(0),
mDispatchingSyncMessage(false),
mDispatchingUrgentMessageCount(0),
mDispatchingSyncMessagePriority(0),
mCurrentTransaction(0),
mRemoteStackDepthGuess(false),
mSawInterruptOutMsg(false),
mAbortOnError(false),
@ -327,8 +382,7 @@ MessageChannel::Clear()
// Free up any memory used by pending messages.
mPending.clear();
mPendingUrgentRequest = nullptr;
mPendingRPCCall = nullptr;
mRecvd = nullptr;
mOutOfTurnReplies.clear();
while (!mDeferred.empty()) {
mDeferred.pop();
@ -488,6 +542,47 @@ MessageChannel::MaybeInterceptSpecialIOMessage(const Message& aMsg)
return false;
}
bool
MessageChannel::ShouldDeferMessage(const Message& aMsg)
{
// Never defer messages that have the highest priority, even async
// ones. This is safe because only the child can send these messages, so
// they can never nest.
if (aMsg.priority() == IPC::Message::PRIORITY_URGENT) {
MOZ_ASSERT(mSide == ParentSide);
return false;
}
// Unless they're urgent, we always defer async messages.
if (!aMsg.is_sync()) {
MOZ_ASSERT(aMsg.priority() == IPC::Message::PRIORITY_NORMAL);
return true;
}
int msgPrio = aMsg.priority();
int waitingPrio = AwaitingSyncReplyPriority();
// Always defer if the priority of the incoming message is less than the
// priority of the message we're awaiting.
if (msgPrio < waitingPrio)
return true;
// Never defer if the message has strictly greater priority.
if (msgPrio > waitingPrio)
return false;
// When both sides send sync messages of the same priority, we resolve the
// race by dispatching in the child and deferring the incoming message in
// the parent. However, the parent still needs to dispatch nested sync
// messages.
//
// Deferring in the parent only sort of breaks message ordering. When the
// child's message comes in, we can pretend the child hasn't quite
// finished sending it yet. Since the message is sync, we know that the
// child hasn't moved on yet.
return mSide == ParentSide && aMsg.transaction_id() != mCurrentTransaction;
}
void
MessageChannel::OnMessageReceivedFromLink(const Message& aMsg)
{
@ -497,19 +592,17 @@ MessageChannel::OnMessageReceivedFromLink(const Message& aMsg)
if (MaybeInterceptSpecialIOMessage(aMsg))
return;
// Regardless of the Interrupt stack, if we're awaiting a sync or urgent 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.
if ((AwaitingSyncReply() && aMsg.is_sync()) ||
(AwaitingUrgentReply() && aMsg.is_urgent()) ||
(AwaitingRPCReply() && aMsg.is_rpc()))
{
if (AwaitingSyncReply() && aMsg.is_sync() && aMsg.is_reply()) {
MOZ_ASSERT(!mRecvd);
mRecvd = new Message(aMsg);
NotifyWorkerThread();
return;
}
// Urgent messages cannot be compressed.
MOZ_ASSERT(!aMsg.compress() || !aMsg.is_urgent());
// Prioritized messages cannot be compressed.
MOZ_ASSERT(!aMsg.compress() || aMsg.priority() == IPC::Message::PRIORITY_NORMAL);
bool compress = (aMsg.compress() && !mPending.empty() &&
mPending.back().type() == aMsg.type() &&
@ -523,20 +616,18 @@ MessageChannel::OnMessageReceivedFromLink(const Message& aMsg)
}
bool shouldWakeUp = AwaitingInterruptReply() ||
// Allow incoming RPCs to be processed inside an urgent message.
(AwaitingUrgentReply() && aMsg.is_rpc()) ||
// Always process urgent messages while blocked.
((AwaitingSyncReply() || AwaitingRPCReply()) && aMsg.is_urgent());
(AwaitingSyncReply() && !ShouldDeferMessage(aMsg));
// There are four cases we're concerned about, relating to the state of the
// There are three cases we're concerned about, relating to the state of the
// main thread:
//
// (1) We are waiting on a sync|rpc reply - main thread is blocked on the
// (1) We are waiting on a sync reply - main thread is blocked on the
// IPC monitor.
// - If the message is high priority, we wake up the main thread to
// deliver the message. Otherwise, we leave it in the mPending queue,
// posting a task to the main event loop, where it will be processed
// once the synchronous reply has been received.
// deliver the message depending on ShouldDeferMessage. Otherwise, we
// leave it in the mPending queue, posting a task to the main event
// loop, where it will be processed once the synchronous reply has been
// received.
//
// (2) We are waiting on an Interrupt reply - main thread is blocked on the
// IPC monitor.
@ -549,47 +640,9 @@ MessageChannel::OnMessageReceivedFromLink(const Message& aMsg)
// blocked. This is okay, since we always check for pending events before
// blocking again.
if (shouldWakeUp && (AwaitingUrgentReply() && aMsg.is_rpc())) {
// If we're receiving an RPC message while blocked on an urgent message,
// we must defer any messages that were not sent as part of the child
// answering the urgent message.
//
// We must also be sure that we will not accidentally defer any RPC
// message that was sent while answering an urgent message. Otherwise,
// we will deadlock.
//
// On the parent side, the current transaction can only transition from 0
// to an ID, either by us issuing an urgent request while not blocked, or
// by receiving an RPC request while not blocked. When we unblock, the
// current transaction is reset to 0.
//
// When the child side receives an urgent message, any RPC messages sent
// before issuing the urgent reply will carry the urgent message's
// transaction ID.
//
// Since AwaitingUrgentReply() implies we are blocked, it also implies
// that we are within a transaction that will not change until we are
// completely unblocked (i.e, the transaction has completed).
if (aMsg.transaction_id() != mCurrentRPCTransaction)
shouldWakeUp = false;
}
if (aMsg.is_urgent()) {
MOZ_ASSERT(!mPendingUrgentRequest);
mPendingUrgentRequest = new Message(aMsg);
} else if (aMsg.is_rpc() && shouldWakeUp) {
// Only use this slot if we need to wake up for an RPC call. Otherwise
// we treat it like a normal async or sync message.
MOZ_ASSERT(!mPendingRPCCall);
mPendingRPCCall = new Message(aMsg);
} else {
mPending.push_back(aMsg);
}
mPending.push_back(aMsg);
if (shouldWakeUp) {
// Always wake up Interrupt waiters, sync waiters for urgent messages,
// RPC waiters for urgent messages, and urgent waiters for RPCs in the
// same transaction.
NotifyWorkerThread();
} else {
// Worker thread is either not blocked on a reply, or this is an
@ -607,7 +660,7 @@ bool
MessageChannel::Send(Message* aMsg, Message* aReply)
{
// See comment in DispatchUrgentMessage.
MaybeScriptBlocker scriptBlocker(this);
MaybeScriptBlocker scriptBlocker(this, true);
// Sanity checks.
AssertWorkerThread();
@ -622,11 +675,16 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
MonitorAutoLock lock(*mMonitor);
IPC_ASSERT(aMsg->is_sync(), "can only Send() sync messages here");
IPC_ASSERT(!DispatchingSyncMessage(), "violation of sync handler invariant");
IPC_ASSERT(!DispatchingUrgentMessage(), "sync messages forbidden while handling urgent message");
IPC_ASSERT(!AwaitingSyncReply(), "nested sync messages are not supported");
IPC_ASSERT(aMsg->priority() >= DispatchingSyncMessagePriority(),
"can't send sync message of a lesser priority than what's being dispatched");
IPC_ASSERT(mAwaitingSyncReplyPriority <= aMsg->priority(),
"nested sync message sends must be of increasing priority");
AutoSetValue<bool> replies(mAwaitingSyncReply, true);
AutoSetValue<int> prio(mAwaitingSyncReplyPriority, aMsg->priority());
AutoEnterTransaction transact(this);
aMsg->set_transaction_id(mCurrentTransaction);
AutoEnterPendingReply replies(mPendingSyncReplies);
if (!SendAndWait(aMsg, aReply))
return false;
@ -634,66 +692,22 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
return true;
}
bool
MessageChannel::UrgentCall(Message* aMsg, Message* aReply)
struct AutoDeferMessages
{
// See comment in DispatchUrgentMessage.
MaybeScriptBlocker scriptBlocker(this);
typedef IPC::Message Message;
AssertWorkerThread();
mMonitor->AssertNotCurrentThreadOwns();
IPC_ASSERT(mSide == ParentSide, "cannot send urgent requests from child");
std::deque<Message>& mQueue;
mozilla::Vector<Message> mDeferred;
#ifdef OS_WIN
SyncStackFrame frame(this, false);
#endif
AutoDeferMessages(std::deque<Message>& queue) : mQueue(queue) {}
~AutoDeferMessages() {
mQueue.insert(mQueue.begin(), mDeferred.begin(), mDeferred.end());
}
CxxStackFrame f(*this, OUT_MESSAGE, aMsg);
MonitorAutoLock lock(*mMonitor);
IPC_ASSERT(!AwaitingInterruptReply(), "urgent calls cannot be issued within Interrupt calls");
IPC_ASSERT(!AwaitingSyncReply(), "urgent calls cannot be issued within sync sends");
AutoEnterRPCTransaction transact(this);
aMsg->set_transaction_id(mCurrentRPCTransaction);
AutoEnterPendingReply replies(mPendingUrgentReplies);
if (!SendAndWait(aMsg, aReply))
return false;
NS_ABORT_IF_FALSE(aReply->is_urgent(), "reply is not urgent");
return true;
}
bool
MessageChannel::RPCCall(Message* aMsg, Message* aReply)
{
// See comment in DispatchUrgentMessage.
MaybeScriptBlocker scriptBlocker(this);
AssertWorkerThread();
mMonitor->AssertNotCurrentThreadOwns();
IPC_ASSERT(mSide == ChildSide, "cannot send rpc messages from parent");
#ifdef OS_WIN
SyncStackFrame frame(this, false);
#endif
CxxStackFrame f(*this, OUT_MESSAGE, aMsg);
MonitorAutoLock lock(*mMonitor);
AutoEnterRPCTransaction transact(this);
aMsg->set_transaction_id(mCurrentRPCTransaction);
AutoEnterPendingReply replies(mPendingRPCReplies);
if (!SendAndWait(aMsg, aReply))
return false;
NS_ABORT_IF_FALSE(aReply->is_rpc(), "expected rpc reply");
return true;
}
void Defer(Message aMsg) {
mDeferred.append(aMsg);
}
};
bool
MessageChannel::SendAndWait(Message* aMsg, Message* aReply)
@ -714,52 +728,44 @@ MessageChannel::SendAndWait(Message* aMsg, Message* aReply)
mLink->SendMessage(msg.forget());
AutoDeferMessages defer(mPending);
while (true) {
// Wait for an event to occur.
while (true) {
if (mRecvd || mPendingUrgentRequest || mPendingRPCCall)
break;
bool maybeTimedOut = !WaitForSyncNotify();
if (!Connected()) {
ReportConnectionError("MessageChannel::SendAndWait");
return false;
}
if (maybeTimedOut && !ShouldContinueFromTimeout())
return false;
}
// We need to make sure that all messages deposited in mPendingRPCCall
// and mPendingUrgentRequest are dispatched before we leave this
// function. Otherwise, there's nothing to wake us up and force us to
// dispatch them.
while (mPendingUrgentRequest) {
if (!ProcessPendingUrgentRequest())
return false;
}
while (mPendingRPCCall) {
if (!ProcessPendingRPCCall())
return false;
while (!mPending.empty()) {
Message msg = mPending.front();
mPending.pop_front();
if (ShouldDeferMessage(msg))
defer.Defer(msg);
else
ProcessPendingRequest(msg);
}
// See if we've received a reply.
if (mRecvd) {
NS_ABORT_IF_FALSE(mRecvd->is_reply(), "expected reply");
MOZ_ASSERT(mRecvd->is_reply(), "expected reply");
if (mRecvd->is_reply_error()) {
mRecvd = nullptr;
return false;
}
NS_ABORT_IF_FALSE(mRecvd->type() == replyType, "wrong reply type");
NS_ABORT_IF_FALSE(mRecvd->seqno() == replySeqno, "wrong sequence number");
MOZ_ASSERT(mRecvd->type() == replyType, "wrong reply type");
MOZ_ASSERT(mRecvd->seqno() == replySeqno);
*aReply = *mRecvd;
mRecvd = nullptr;
return true;
}
bool maybeTimedOut = !WaitForSyncNotify();
if (!Connected()) {
ReportConnectionError("MessageChannel::SendAndWait");
return false;
}
if (maybeTimedOut && !ShouldContinueFromTimeout())
return false;
}
return true;
@ -767,16 +773,6 @@ MessageChannel::SendAndWait(Message* aMsg, Message* aReply)
bool
MessageChannel::Call(Message* aMsg, Message* aReply)
{
if (aMsg->is_urgent())
return UrgentCall(aMsg, aReply);
if (aMsg->is_rpc())
return RPCCall(aMsg, aReply);
return InterruptCall(aMsg, aReply);
}
bool
MessageChannel::InterruptCall(Message* aMsg, Message* aReply)
{
AssertWorkerThread();
mMonitor->AssertNotCurrentThreadOwns();
@ -796,13 +792,12 @@ MessageChannel::InterruptCall(Message* aMsg, Message* aReply)
}
// Sanity checks.
IPC_ASSERT(!AwaitingSyncReply() && !AwaitingUrgentReply(),
"cannot issue Interrupt call whiel blocked on sync or urgent");
IPC_ASSERT(!DispatchingSyncMessage() || aMsg->priority() == IPC::Message::PRIORITY_HIGH,
IPC_ASSERT(!AwaitingSyncReply(),
"cannot issue Interrupt call while blocked on sync request");
IPC_ASSERT(!DispatchingSyncMessage(),
"violation of sync handler invariant");
IPC_ASSERT(aMsg->is_interrupt(), "can only Call() Interrupt messages here");
nsAutoPtr<Message> msg(aMsg);
msg->set_seqno(NextSeqno());
@ -818,7 +813,7 @@ MessageChannel::InterruptCall(Message* aMsg, Message* aReply)
// trying another loop iteration will be futile because
// channel state will have been cleared
if (!Connected()) {
ReportConnectionError("MessageChannel::InterruptCall");
ReportConnectionError("MessageChannel::Call");
return false;
}
@ -845,14 +840,8 @@ MessageChannel::InterruptCall(Message* aMsg, Message* aReply)
Message recvd;
MessageMap::iterator it;
if (mPendingUrgentRequest) {
recvd = *mPendingUrgentRequest;
mPendingUrgentRequest = nullptr;
} else if (mPendingRPCCall) {
recvd = *mPendingRPCCall;
mPendingRPCCall = nullptr;
} else if ((it = mOutOfTurnReplies.find(mInterruptStack.top().seqno()))
!= mOutOfTurnReplies.end())
if ((it = mOutOfTurnReplies.find(mInterruptStack.top().seqno()))
!= mOutOfTurnReplies.end())
{
recvd = it->second;
mOutOfTurnReplies.erase(it);
@ -870,11 +859,8 @@ MessageChannel::InterruptCall(Message* aMsg, Message* aReply)
// If the message is not Interrupt, we can dispatch it as normal.
if (!recvd.is_interrupt()) {
// Other side should be blocked.
IPC_ASSERT(!recvd.is_sync() || mPending.empty(), "other side should be blocked");
{
AutoEnterRPCTransaction transaction(this, &recvd);
AutoEnterTransaction transaction(this, &recvd);
MonitorAutoUnlock unlock(*mMonitor);
CxxStackFrame frame(*this, IN_MESSAGE, &recvd);
DispatchMessage(recvd);
@ -955,15 +941,13 @@ MessageChannel::InterruptEventOccurred()
return (!Connected() ||
!mPending.empty() ||
mPendingUrgentRequest ||
mPendingRPCCall ||
(!mOutOfTurnReplies.empty() &&
mOutOfTurnReplies.find(mInterruptStack.top().seqno()) !=
mOutOfTurnReplies.end()));
}
bool
MessageChannel::ProcessPendingUrgentRequest()
MessageChannel::ProcessPendingRequest(Message aUrgent)
{
AssertWorkerThread();
mMonitor->AssertCurrentThreadOwns();
@ -978,57 +962,16 @@ MessageChannel::ProcessPendingUrgentRequest()
// to save the reply.
nsAutoPtr<Message> savedReply(mRecvd.forget());
// We're the child process. We should not be receiving RPC calls.
IPC_ASSERT(!mPendingRPCCall, "unexpected RPC call");
nsAutoPtr<Message> recvd(mPendingUrgentRequest.forget());
{
// In order to send the parent RPC messages and guarantee it will
// wake up, we must re-use its transaction.
AutoEnterRPCTransaction transaction(this, recvd);
AutoEnterTransaction transaction(this, &aUrgent);
MonitorAutoUnlock unlock(*mMonitor);
DispatchUrgentMessage(*recvd);
DispatchMessage(aUrgent);
}
if (!Connected()) {
ReportConnectionError("MessageChannel::DispatchUrgentMessage");
return false;
}
// In between having dispatched our reply to the parent process, and
// re-acquiring the monitor, the parent process could have already
// processed that reply and sent the reply to our sync message. If so,
// our saved reply should be empty.
IPC_ASSERT(!mRecvd || !savedReply, "unknown reply");
if (!mRecvd)
mRecvd = savedReply.forget();
return true;
}
bool
MessageChannel::ProcessPendingRPCCall()
{
AssertWorkerThread();
mMonitor->AssertCurrentThreadOwns();
// See comment above re: mRecvd replies and incoming calls.
nsAutoPtr<Message> savedReply(mRecvd.forget());
IPC_ASSERT(!mPendingUrgentRequest, "unexpected urgent message");
nsAutoPtr<Message> recvd(mPendingRPCCall.forget());
{
// If we are not currently in a transaction, this will begin one,
// and the link thread will not wake us up for any RPC messages not
// apart of this transaction. If we are already in a transaction,
// then this will assert that we're still in the same transaction.
AutoEnterRPCTransaction transaction(this, recvd);
MonitorAutoUnlock unlock(*mMonitor);
DispatchRPCMessage(*recvd);
}
if (!Connected()) {
ReportConnectionError("MessageChannel::DispatchRPCMessage");
ReportConnectionError("MessageChannel::ProcessPendingRequest");
return false;
}
@ -1053,18 +996,6 @@ MessageChannel::DequeueOne(Message *recvd)
return false;
}
if (mPendingUrgentRequest) {
*recvd = *mPendingUrgentRequest;
mPendingUrgentRequest = nullptr;
return true;
}
if (mPendingRPCCall) {
*recvd = *mPendingRPCCall;
mPendingRPCCall = nullptr;
return true;
}
if (!mDeferred.empty())
MaybeUndeferIncall();
@ -1097,8 +1028,8 @@ MessageChannel::OnMaybeDequeueOne()
{
// We should not be in a transaction yet if we're not blocked.
MOZ_ASSERT(mCurrentRPCTransaction == 0);
AutoEnterRPCTransaction transaction(this, &recvd);
MOZ_ASSERT(mCurrentTransaction == 0);
AutoEnterTransaction transaction(this, &recvd);
MonitorAutoUnlock unlock(*mMonitor);
@ -1113,12 +1044,8 @@ MessageChannel::DispatchMessage(const Message &aMsg)
{
if (aMsg.is_sync())
DispatchSyncMessage(aMsg);
else if (aMsg.is_urgent())
DispatchUrgentMessage(aMsg);
else if (aMsg.is_interrupt())
DispatchInterruptMessage(aMsg, 0);
else if (aMsg.is_rpc())
DispatchRPCMessage(aMsg);
else
DispatchAsyncMessage(aMsg);
}
@ -1130,72 +1057,36 @@ MessageChannel::DispatchSyncMessage(const Message& aMsg)
Message *reply = nullptr;
mDispatchingSyncMessage = true;
Result rv = mListener->OnMessageReceived(aMsg, reply);
mDispatchingSyncMessage = false;
if (!MaybeHandleError(rv, aMsg, "DispatchSyncMessage")) {
delete reply;
reply = new Message();
reply->set_sync();
reply->set_reply();
reply->set_reply_error();
}
reply->set_seqno(aMsg.seqno());
MonitorAutoLock lock(*mMonitor);
if (ChannelConnected == mChannelState)
mLink->SendMessage(reply);
}
void
MessageChannel::DispatchUrgentMessage(const Message& aMsg)
{
AssertWorkerThread();
MOZ_ASSERT(aMsg.is_urgent());
Message *reply = nullptr;
MOZ_ASSERT(NS_IsMainThread());
int prio = aMsg.priority();
// We don't want to run any code that might run a nested event loop here, so
// we avoid running event handlers. Once we've sent the response to the
// urgent message, it's okay to run event handlers again since the parent is
// no longer blocked.
//
// We also put script blockers at the start of every synchronous send
// call. That way we won't run any scripts while waiting for a response to
// another message. Running scripts could cause us to send more sync
// messages, and the other side wouldn't know what to do if it received a
// sync message while dispatching another sync message. (In practice, the
// other side would queue the second sync message, while we would need it to
// dispatch that message before sending the reply to the original sync
// message. Otherwise the replies would come out of order.)
//
// We omit the script blocker for InterruptCall since interrupt messages are
// designed to handle this sort of re-entry. (For example, if the child
// sends an intr message to the parent, the child will process any queued
// async messages from the parent while waiting for the intr response. In
// doing so, the child could trigger sync messages to be sent to the parent
// while the parent is still dispatching the intr message. If the parent
// sends an intr reply while the child is waiting for a sync response, the
// intr reply will be queued in mPending. Once the sync reply is received,
// InterruptCall will find the intr reply in mPending and run it.) The
// situation where we run event handlers while waiting for an intr reply is
// no different than the one where we process async messages while waiting
// for an intr reply.
MaybeScriptBlocker scriptBlocker(this);
MOZ_ASSERT_IF(prio > IPC::Message::PRIORITY_NORMAL, NS_IsMainThread());
MaybeScriptBlocker scriptBlocker(this, prio > IPC::Message::PRIORITY_NORMAL);
gDispatchingUrgentMessageCount++;
mDispatchingUrgentMessageCount++;
Result rv = mListener->OnCallReceived(aMsg, reply);
mDispatchingUrgentMessageCount--;
gDispatchingUrgentMessageCount--;
IPC_ASSERT(prio >= mDispatchingSyncMessagePriority,
"priority inversion while dispatching sync message");
IPC_ASSERT(prio >= mAwaitingSyncReplyPriority,
"dispatching a message of lower priority while waiting for a response");
if (!MaybeHandleError(rv, aMsg, "DispatchUrgentMessage")) {
bool dummy;
bool& blockingVar = ShouldBlockScripts() ? gParentIsBlocked : dummy;
Result rv;
{
AutoSetValue<bool> blocked(blockingVar, true);
AutoSetValue<bool> sync(mDispatchingSyncMessage, true);
AutoSetValue<int> prioSet(mDispatchingSyncMessagePriority, prio);
rv = mListener->OnMessageReceived(aMsg, reply);
}
if (!MaybeHandleError(rv, aMsg, "DispatchSyncMessage")) {
delete reply;
reply = new Message();
reply->set_urgent();
reply->set_sync();
reply->set_priority(aMsg.priority());
reply->set_reply();
reply->set_reply_error();
}
@ -1206,33 +1097,11 @@ MessageChannel::DispatchUrgentMessage(const Message& aMsg)
mLink->SendMessage(reply);
}
void
MessageChannel::DispatchRPCMessage(const Message& aMsg)
{
AssertWorkerThread();
MOZ_ASSERT(aMsg.is_rpc());
Message *reply = nullptr;
if (!MaybeHandleError(mListener->OnCallReceived(aMsg, reply), aMsg, "DispatchRPCMessage")) {
delete reply;
reply = new Message();
reply->set_rpc();
reply->set_reply();
reply->set_reply_error();
}
reply->set_seqno(aMsg.seqno());
MonitorAutoLock lock(*mMonitor);
if (ChannelConnected == mChannelState)
mLink->SendMessage(reply);
}
void
MessageChannel::DispatchAsyncMessage(const Message& aMsg)
{
AssertWorkerThread();
MOZ_ASSERT(!aMsg.is_interrupt() && !aMsg.is_sync() && !aMsg.is_urgent());
MOZ_ASSERT(!aMsg.is_interrupt() && !aMsg.is_sync());
if (aMsg.routing_id() == MSG_ROUTING_NONE) {
NS_RUNTIMEABORT("unhandled special message!");
@ -1346,6 +1215,7 @@ MessageChannel::MaybeUndeferIncall()
IPC_ASSERT(0 < mRemoteStackDepthGuess, "fatal logic error");
--mRemoteStackDepthGuess;
MOZ_ASSERT(call.priority() == IPC::Message::PRIORITY_NORMAL);
mPending.push_back(call);
}
@ -1618,7 +1488,7 @@ MessageChannel::OnChannelErrorFromLink()
if (InterruptStackDepth() > 0)
NotifyWorkerThread();
if (AwaitingSyncReply() || AwaitingRPCReply() || AwaitingUrgentReply())
if (AwaitingSyncReply())
NotifyWorkerThread();
if (ChannelClosing != mChannelState) {
@ -1856,9 +1726,9 @@ MessageChannel::DumpInterruptStack(const char* const pfx) const
}
bool
ProcessingUrgentMessages()
ParentProcessIsBlocked()
{
return gDispatchingUrgentMessageCount > 0;
return gParentIsBlocked;
}
} // ipc

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

@ -226,14 +226,9 @@ class MessageChannel : HasResultCodes
// up to process urgent calls from the parent.
bool SendAndWait(Message* aMsg, Message* aReply);
bool RPCCall(Message* aMsg, Message* aReply);
bool InterruptCall(Message* aMsg, Message* aReply);
bool UrgentCall(Message* aMsg, Message* aReply);
bool InterruptEventOccurred();
bool ProcessPendingUrgentRequest();
bool ProcessPendingRPCCall();
bool ProcessPendingRequest(Message aUrgent);
void MaybeUndeferIncall();
void EnqueuePendingMessages();
@ -327,15 +322,11 @@ class MessageChannel : HasResultCodes
// Returns true if we're blocking waiting for a reply.
bool AwaitingSyncReply() const {
mMonitor->AssertCurrentThreadOwns();
return mPendingSyncReplies > 0;
return mAwaitingSyncReply;
}
bool AwaitingUrgentReply() const {
int AwaitingSyncReplyPriority() const {
mMonitor->AssertCurrentThreadOwns();
return mPendingUrgentReplies > 0;
}
bool AwaitingRPCReply() const {
mMonitor->AssertCurrentThreadOwns();
return mPendingRPCReplies > 0;
return mAwaitingSyncReplyPriority;
}
bool AwaitingInterruptReply() const {
mMonitor->AssertCurrentThreadOwns();
@ -344,12 +335,13 @@ class MessageChannel : HasResultCodes
// Returns true if we're dispatching a sync message's callback.
bool DispatchingSyncMessage() const {
AssertWorkerThread();
return mDispatchingSyncMessage;
}
// Returns true if we're dispatching an urgent message's callback.
bool DispatchingUrgentMessage() const {
return mDispatchingUrgentMessageCount > 0;
int DispatchingSyncMessagePriority() const {
AssertWorkerThread();
return mDispatchingSyncMessagePriority;
}
bool Connected() const;
@ -367,6 +359,7 @@ class MessageChannel : HasResultCodes
// Tell the IO thread to close the channel and wait for it to ACK.
void SynchronouslyClose();
bool ShouldDeferMessage(const Message& aMsg);
void OnMessageReceivedFromLink(const Message& aMsg);
void OnChannelErrorFromLink();
@ -460,29 +453,30 @@ class MessageChannel : HasResultCodes
static bool sIsPumpingMessages;
class AutoEnterPendingReply {
template<class T>
class AutoSetValue {
public:
explicit AutoEnterPendingReply(size_t &replyVar)
: mReplyVar(replyVar)
explicit AutoSetValue(T &var, const T &newValue)
: mVar(var), mPrev(var)
{
mReplyVar++;
mVar = newValue;
}
~AutoEnterPendingReply() {
mReplyVar--;
~AutoSetValue() {
mVar = mPrev;
}
private:
size_t& mReplyVar;
T& mVar;
T mPrev;
};
// Worker-thread only; type we're expecting for the reply to a sync
// out-message. This will never be greater than 1.
size_t mPendingSyncReplies;
// Worker thread only.
bool mAwaitingSyncReply;
int mAwaitingSyncReplyPriority;
// Worker-thread only; Number of urgent and rpc replies we're waiting on.
// These are mutually exclusive since one channel cannot have outcalls of
// both kinds.
size_t mPendingUrgentReplies;
size_t mPendingRPCReplies;
// Set while we are dispatching a synchronous message. Only for use on the
// worker thread.
bool mDispatchingSyncMessage;
int mDispatchingSyncMessagePriority;
// When we send an urgent request from the parent process, we could race
// with an RPC message that was issued by the child beforehand. In this
@ -498,40 +492,40 @@ class MessageChannel : HasResultCodes
// messages the parent receives, not apart of this transaction, are
// deferred. When issuing RPC/urgent requests on top of a started
// transaction, the initiating transaction ID is used.
//
//
// To ensure IDs are unique, we use sequence numbers for transaction IDs,
// which grow in opposite directions from child to parent.
// The current transaction ID.
int32_t mCurrentRPCTransaction;
int32_t mCurrentTransaction;
class AutoEnterRPCTransaction
class AutoEnterTransaction
{
public:
explicit AutoEnterRPCTransaction(MessageChannel *aChan)
explicit AutoEnterTransaction(MessageChannel *aChan)
: mChan(aChan),
mOldTransaction(mChan->mCurrentRPCTransaction)
mOldTransaction(mChan->mCurrentTransaction)
{
mChan->mMonitor->AssertCurrentThreadOwns();
if (mChan->mCurrentRPCTransaction == 0)
mChan->mCurrentRPCTransaction = mChan->NextSeqno();
if (mChan->mCurrentTransaction == 0)
mChan->mCurrentTransaction = mChan->NextSeqno();
}
AutoEnterRPCTransaction(MessageChannel *aChan, Message *message)
explicit AutoEnterTransaction(MessageChannel *aChan, Message *message)
: mChan(aChan),
mOldTransaction(mChan->mCurrentRPCTransaction)
mOldTransaction(mChan->mCurrentTransaction)
{
mChan->mMonitor->AssertCurrentThreadOwns();
if (!message->is_rpc() && !message->is_urgent())
if (!message->is_sync())
return;
MOZ_ASSERT_IF(mChan->mSide == ParentSide,
!mOldTransaction || mOldTransaction == message->transaction_id());
mChan->mCurrentRPCTransaction = message->transaction_id();
MOZ_ASSERT_IF(mChan->mSide == ParentSide && mOldTransaction != message->transaction_id(),
!mOldTransaction || message->priority() > mChan->AwaitingSyncReplyPriority());
mChan->mCurrentTransaction = message->transaction_id();
}
~AutoEnterRPCTransaction() {
~AutoEnterTransaction() {
mChan->mMonitor->AssertCurrentThreadOwns();
mChan->mCurrentRPCTransaction = mOldTransaction;
mChan->mCurrentTransaction = mOldTransaction;
}
private:
@ -543,12 +537,6 @@ class MessageChannel : HasResultCodes
// on the I/O thread and then read and cleared by the worker thread.
nsAutoPtr<Message> mRecvd;
// Set while we are dispatching a synchronous message.
bool mDispatchingSyncMessage;
// Count of the recursion depth of dispatching urgent messages.
size_t mDispatchingUrgentMessageCount;
// Queue of all incoming messages, except for replies to sync and urgent
// messages, which are delivered directly to mRecvd, and any pending urgent
// incall, which is stored in mPendingUrgentRequest.
@ -587,18 +575,6 @@ class MessageChannel : HasResultCodes
//
MessageQueue mPending;
// Note that these two pointers are mutually exclusive. One channel cannot
// send both urgent requests (parent -> child) and RPC calls (child->parent).
// Also note that since initiating either requires blocking, they cannot
// queue up on the other side. One message slot is enough.
//
// Normally, all other message types are deferred into into mPending, and
// only these two types have special treatment (since they wake up blocked
// requests). However, when an RPC in-call races with an urgent out-call,
// the RPC message will be put into mPending instead of its slot below.
nsAutoPtr<Message> mPendingUrgentRequest;
nsAutoPtr<Message> mPendingRPCCall;
// Stack of all the out-calls on which this channel is awaiting responses.
// Each stack refers to a different protocol and the stacks are mutually
// exclusive: multiple outcalls of the same kind cannot be initiated while
@ -676,7 +652,7 @@ class MessageChannel : HasResultCodes
};
bool
ProcessingUrgentMessages();
ParentProcessIsBlocked();
} // namespace ipc
} // namespace mozilla

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

@ -4,6 +4,10 @@
import sys
NORMAL_PRIORITY = 1
HIGH_PRIORITY = 2
URGENT_PRIORITY = 3
class Visitor:
def defaultVisit(self, node):
raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% (
@ -214,8 +218,6 @@ class INTR(PrettyPrinted):
pretty = 'intr'
class SYNC(PrettyPrinted):
pretty = 'sync'
class RPC(PrettyPrinted):
pretty = 'rpc'
class INOUT(PrettyPrinted):
pretty = 'inout'
@ -234,6 +236,7 @@ class Protocol(NamespacedNode):
def __init__(self, loc):
NamespacedNode.__init__(self, loc)
self.sendSemantics = ASYNC
self.priority = NORMAL_PRIORITY
self.spawnsStmts = [ ]
self.bridgesStmts = [ ]
self.opensStmts = [ ]
@ -293,6 +296,7 @@ class MessageDecl(Node):
Node.__init__(self, loc)
self.name = None
self.sendSemantics = ASYNC
self.priority = NORMAL_PRIORITY
self.direction = None
self.inParams = [ ]
self.outParams = [ ]
@ -304,9 +308,6 @@ class MessageDecl(Node):
def addOutParams(self, outParamsList):
self.outParams += outParamsList
def hasReply(self):
return self.sendSemantics is SYNC or self.sendSemantics is INTR
class Transition(Node):
def __init__(self, loc, trigger, msg, toStates):
Node.__init__(self, loc)

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

@ -277,13 +277,13 @@ def _putInNamespaces(cxxthing, namespaces):
def _sendPrefix(msgtype):
"""Prefix of the name of the C++ method that sends |msgtype|."""
if msgtype.isInterrupt() or msgtype.isRpc():
if msgtype.isInterrupt():
return 'Call'
return 'Send'
def _recvPrefix(msgtype):
"""Prefix of the name of the C++ method that handles |msgtype|."""
if msgtype.isInterrupt() or msgtype.isRpc():
if msgtype.isInterrupt():
return 'Answer'
return 'Recv'
@ -2984,7 +2984,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
ExprCall(ExprSelect(p.channelVar(), '.', 'Close'))))
self.cls.addstmts([ closemeth, Whitespace.NL ])
if ptype.talksSync() or ptype.talksInterrupt():
if ptype.isSync() or ptype.isInterrupt():
# SetReplyTimeoutMs()
timeoutvar = ExprVar('aTimeoutMs')
settimeout = MethodDefn(MethodDecl(
@ -3053,9 +3053,11 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
msgtype = ExprCall(ExprSelect(msgvar, '.', 'type'), [ ])
self.asyncSwitch = StmtSwitch(msgtype)
if toplevel.talksSync():
self.syncSwitch = None
self.interruptSwitch = None
if toplevel.isSync() or toplevel.isInterrupt():
self.syncSwitch = StmtSwitch(msgtype)
if toplevel.talksRpc():
if toplevel.isInterrupt():
self.interruptSwitch = StmtSwitch(msgtype)
# implement Send*() methods and add dispatcher cases to
@ -3072,9 +3074,9 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
default = StmtBlock()
default.addstmt(StmtReturn(_Result.NotKnown))
self.asyncSwitch.addcase(DefaultLabel(), default)
if toplevel.talksSync():
if toplevel.isSync() or toplevel.isInterrupt():
self.syncSwitch.addcase(DefaultLabel(), default)
if toplevel.talksRpc():
if toplevel.isInterrupt():
self.interruptSwitch.addcase(DefaultLabel(), default)
# FIXME/bug 535053: only manager protocols and non-manager
@ -3151,10 +3153,6 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
hasReply=0, dispatches=dispatches),
Whitespace.NL
])
if not toplevel.talksRpc():
self.interruptSwitch = None
if not toplevel.talksSync():
self.syncSwitch = None
self.cls.addstmts([
makeHandlerMethod('OnMessageReceived', self.syncSwitch,
hasReply=1, dispatches=dispatches),
@ -3190,7 +3188,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
self.cls.addstmts([ gettypetag, Whitespace.NL ])
# OnReplyTimeout()
if toplevel.talksSync() or toplevel.talksInterrupt():
if toplevel.isSync() or toplevel.isInterrupt():
ontimeout = MethodDefn(
MethodDecl('OnReplyTimeout', ret=Type.BOOL))
@ -3278,7 +3276,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
# User-facing shmem methods
self.cls.addstmts(self.makeShmemIface())
if (ptype.isToplevel() and ptype.talksInterrupt()):
if (ptype.isToplevel() and ptype.isInterrupt()):
processnative = MethodDefn(
MethodDecl('ProcessNativeEventsInInterruptCall', ret=Type.VOID))
@ -4780,22 +4778,22 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
def visitMessageDecl(self, md):
isctor = md.decl.type.isCtor()
isdtor = md.decl.type.isDtor()
sems = md.decl.type.sendSemantics
decltype = md.decl.type
sendmethod = None
helpermethod = None
recvlbl, recvcase = None, None
def addRecvCase(lbl, case):
if sems is ipdl.ast.ASYNC:
if decltype.isAsync():
self.asyncSwitch.addcase(lbl, case)
elif sems is ipdl.ast.SYNC:
elif decltype.isSync():
self.syncSwitch.addcase(lbl, case)
elif sems is ipdl.ast.INTR or sems is ipdl.ast.RPC:
elif decltype.isInterrupt():
self.interruptSwitch.addcase(lbl, case)
else: assert 0
if self.sendsMessage(md):
isasync = (sems is ipdl.ast.ASYNC)
isasync = decltype.isAsync()
if isctor:
self.cls.addstmts([ self.genHelperCtor(md), Whitespace.NL ])
@ -5185,21 +5183,14 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
if md.decl.type.isSync():
stmts.append(StmtExpr(ExprCall(
ExprSelect(var, '->', 'set_sync'))))
elif md.decl.type.isRpc():
# We use urgent messages from the parent to the child and
# RPC messages from the child to the parent. However,
# replies should always be sent using the same semantics
# as the original message, so we need to flip.
if (self.side == 'parent') ^ reply:
stmts.append(StmtExpr(ExprCall(
ExprSelect(var, '->', 'set_urgent'))))
else:
stmts.append(StmtExpr(ExprCall(
ExprSelect(var, '->', 'set_rpc'))))
elif md.decl.type.isInterrupt():
stmts.append(StmtExpr(ExprCall(
ExprSelect(var, '->', 'set_interrupt'))))
stmts.append(StmtExpr(ExprCall(
ExprSelect(var, '->', 'set_priority'),
args=[ ExprLiteral.Int(md.decl.type.priority) ])))
if reply:
stmts.append(StmtExpr(ExprCall(
ExprSelect(var, '->', 'set_reply'))))

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

@ -127,19 +127,21 @@ reserved = set((
'delete', # reserve 'delete' to prevent its use
'from',
'goto',
'high',
'include',
'intr',
'manager',
'manages',
'namespace',
'normal',
'nullable',
'opens',
'or',
'parent',
'prio',
'protocol',
'recv',
'returns',
'rpc',
'send',
'spawns',
'start',
@ -147,9 +149,11 @@ reserved = set((
'struct',
'sync',
'union',
'upto',
'urgent',
'using'))
tokens = [
'COLONCOLON', 'ID', 'STRING'
'COLONCOLON', 'ID', 'STRING',
] + [ r.upper() for r in reserved ]
t_COLONCOLON = '::'
@ -349,11 +353,12 @@ def p_ComponentTypes(p):
p[0] = p[1]
def p_ProtocolDefn(p):
"""ProtocolDefn : OptionalSendSemanticsQual PROTOCOL ID '{' ProtocolBody '}' ';'"""
"""ProtocolDefn : OptionalProtocolSendSemanticsQual PROTOCOL ID '{' ProtocolBody '}' ';'"""
protocol = p[5]
protocol.loc = locFromTok(p, 2)
protocol.name = p[3]
protocol.sendSemantics = p[1]
protocol.priorityRange = p[1][0]
protocol.sendSemantics = p[1][1]
p[0] = protocol
if Parser.current.type == 'header':
@ -495,7 +500,8 @@ def p_MessageDirectionLabel(p):
def p_MessageDecl(p):
"""MessageDecl : OptionalSendSemanticsQual MessageBody"""
msg = p[2]
msg.sendSemantics = p[1]
msg.priority = p[1][0]
msg.sendSemantics = p[1][1]
if Parser.current.direction is None:
_error(msg.loc, 'missing message direction')
@ -615,24 +621,67 @@ def p_State(p):
##--------------------
## Minor stuff
def p_Priority(p):
"""Priority : NORMAL
| HIGH
| URGENT"""
prios = {'normal': 1,
'high': 2,
'urgent': 3}
p[0] = prios[p[1]]
def p_OptionalSendSemanticsQual(p):
"""OptionalSendSemanticsQual : SendSemanticsQual
| """
if 2 == len(p): p[0] = p[1]
else: p[0] = ASYNC
else: p[0] = [ NORMAL_PRIORITY, ASYNC ]
def p_SendSemanticsQual(p):
"""SendSemanticsQual : ASYNC
| INTR
| RPC
| SYNC"""
s = p[1]
if 'async' == s: p[0] = ASYNC
elif 'intr' == s: p[0] = INTR
elif 'sync' == s: p[0] = SYNC
elif 'rpc' == s: p[0] = RPC
| SYNC
| PRIO '(' Priority ')' ASYNC
| PRIO '(' Priority ')' SYNC
| INTR"""
if p[1] == 'prio':
mtype = p[5]
prio = p[3]
else:
assert 0
mtype = p[1]
prio = NORMAL_PRIORITY
if mtype == 'async': mtype = ASYNC
elif mtype == 'sync': mtype = SYNC
elif mtype == 'intr': mtype = INTR
else: assert 0
p[0] = [ prio, mtype ]
def p_OptionalProtocolSendSemanticsQual(p):
"""OptionalProtocolSendSemanticsQual : ProtocolSendSemanticsQual
| """
if 2 == len(p): p[0] = p[1]
else: p[0] = [ (NORMAL_PRIORITY, NORMAL_PRIORITY), ASYNC ]
def p_ProtocolSendSemanticsQual(p):
"""ProtocolSendSemanticsQual : ASYNC
| SYNC
| PRIO '(' Priority UPTO Priority ')' ASYNC
| PRIO '(' Priority UPTO Priority ')' SYNC
| PRIO '(' Priority UPTO Priority ')' INTR
| INTR"""
if p[1] == 'prio':
mtype = p[7]
prio = (p[3], p[5])
else:
mtype = p[1]
prio = (NORMAL_PRIORITY, NORMAL_PRIORITY)
if mtype == 'async': mtype = ASYNC
elif mtype == 'sync': mtype = SYNC
elif mtype == 'intr': mtype = INTR
else: assert 0
p[0] = [ prio, mtype ]
def p_ParamList(p):
"""ParamList : ParamList ',' Param

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

@ -6,8 +6,10 @@
import os, sys
from ipdl.ast import CxxInclude, Decl, Loc, QualifiedId, State, StructDecl, TransitionStmt
from ipdl.ast import TypeSpec, UnionDecl, UsingStmt, Visitor, ASYNC, SYNC, INTR
from ipdl.ast import IN, OUT, INOUT, ANSWER, CALL, RECV, SEND, RPC
from ipdl.ast import TypeSpec, UnionDecl, UsingStmt, Visitor
from ipdl.ast import ASYNC, SYNC, INTR
from ipdl.ast import IN, OUT, INOUT, ANSWER, CALL, RECV, SEND
from ipdl.ast import NORMAL_PRIORITY, HIGH_PRIORITY, URGENT_PRIORITY
import ipdl.builtin as builtin
_DELETE_MSG = '__delete__'
@ -204,24 +206,29 @@ class IPDLType(Type):
def isChmod(self): return False
def isFD(self): return False
def isAsync(self): return self.sendSemantics is ASYNC
def isSync(self): return self.sendSemantics is SYNC
def isAsync(self): return self.sendSemantics == ASYNC
def isSync(self): return self.sendSemantics == SYNC
def isInterrupt(self): return self.sendSemantics is INTR
def isRpc(self): return self.sendSemantics is RPC
def talksAsync(self): return True
def talksSync(self): return self.isSync() or self.isRpc() or self.isInterrupt()
def talksRpc(self): return self.isRpc() or self.isInterrupt()
def talksInterrupt(self): return self.isInterrupt()
def hasReply(self): return (self.isSync() or self.isInterrupt())
def hasReply(self): return (self.isSync()
or self.isInterrupt()
or self.isRpc())
@classmethod
def convertsTo(cls, lesser, greater):
if (lesser.priorityRange[0] < greater.priorityRange[0] or
lesser.priorityRange[1] > greater.priorityRange[1]):
return False
if lesser.isAsync():
return True
elif lesser.isSync() and not greater.isAsync():
return True
elif greater.isInterrupt():
return True
return False
def needsMoreJuiceThan(self, o):
return (o.isAsync() and not self.isAsync()
or o.isSync() and self.isRpc()
or o.isRpc() and self.isInterrupt())
return not IPDLType.convertsTo(self, o)
class StateType(IPDLType):
def __init__(self, protocol, name, start=False):
@ -235,11 +242,13 @@ class StateType(IPDLType):
return self.name()
class MessageType(IPDLType):
def __init__(self, sendSemantics, direction,
def __init__(self, priority, sendSemantics, direction,
ctor=False, dtor=False, cdtype=None, compress=False):
assert not (ctor and dtor)
assert not (ctor or dtor) or type is not None
self.priority = priority
self.priorityRange = (priority, priority)
self.sendSemantics = sendSemantics
self.direction = direction
self.params = [ ]
@ -275,8 +284,9 @@ class Bridge:
return hash(self.parent) + hash(self.child)
class ProtocolType(IPDLType):
def __init__(self, qname, sendSemantics, stateless=False):
def __init__(self, qname, priorityRange, sendSemantics, stateless=False):
self.qname = qname
self.priorityRange = priorityRange
self.sendSemantics = sendSemantics
self.spawns = set() # ProtocolType
self.opens = set() # ProtocolType
@ -684,7 +694,7 @@ class GatherDecls(TcheckVisitor):
fullname = str(qname)
p.decl = self.declare(
loc=p.loc,
type=ProtocolType(qname, p.sendSemantics,
type=ProtocolType(qname, p.priorityRange, p.sendSemantics,
stateless=(0 == len(p.transitionStmts))),
shortname=p.name,
fullname=fullname)
@ -1083,7 +1093,7 @@ class GatherDecls(TcheckVisitor):
# enter message scope
self.symtab.enterScope(md)
msgtype = MessageType(md.sendSemantics, md.direction,
msgtype = MessageType(md.priority, md.sendSemantics, md.direction,
ctor=isctor, dtor=isdtor, cdtype=cdtype,
compress=(md.compress == 'compress'))
@ -1457,7 +1467,22 @@ class CheckTypes(TcheckVisitor):
loc = md.decl.loc
if mtype.isSync() and (mtype.isOut() or mtype.isInout()):
if mtype.priority == HIGH_PRIORITY and not mtype.isSync():
self.error(
loc,
"high priority messages must be sync (here, message `%s' in protocol `%s')",
mname, pname)
if mtype.priority == URGENT_PRIORITY and (mtype.isOut() or mtype.isInout()):
self.error(
loc,
"urgent parent-to-child messages are verboten (here, message `%s' in protocol `%s')",
mname, pname)
# We allow high priority sync messages to be sent from the
# parent. Normal and urgent sync messages can only come from
# the child.
if mtype.isSync() and mtype.priority == NORMAL_PRIORITY and (mtype.isOut() or mtype.isInout()):
self.error(
loc,
"sync parent-to-child messages are verboten (here, message `%s' in protocol `%s')",

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

@ -19,7 +19,7 @@ include $(topsrcdir)/config/rules.mk
IPDLUNITTEST_BIN = $(DEPTH)/dist/bin/ipdlunittest$(BIN_SUFFIX)
IPDLUnitTests.cpp : Makefile.in $(GENTESTER) $(TESTER_TEMPLATE) $(IPDLTESTHDRS)
IPDLUnitTests.cpp : Makefile.in moz.build $(GENTESTER) $(TESTER_TEMPLATE) $(IPDLTESTHDRS)
$(PYTHON) $(GENTESTER) $(TESTER_TEMPLATE) -t $(IPDLTESTS) -e $(EXTRA_PROTOCOLS) > $@
check-proc::

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

@ -0,0 +1,18 @@
namespace mozilla {
namespace _ipdltest {
prio(normal upto urgent) sync protocol PTestHighestPrio
{
parent:
prio(urgent) async Msg1();
sync Msg2();
prio(urgent) async Msg3();
prio(urgent) sync Msg4();
child:
async Start();
prio(high) sync StartInner();
};
}
}

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

@ -1,26 +1,25 @@
namespace mozilla {
namespace _ipdltest {
intr protocol PTestRPC
prio(normal upto high) sync protocol PTestRPC
{
parent:
rpc Test1_Start() returns (uint32_t result);
rpc Test1_InnerEvent() returns (uint32_t result);
prio(high) sync Test1_Start() returns (uint32_t result);
prio(high) sync Test1_InnerEvent() returns (uint32_t result);
async Test2_Start();
rpc Test2_OutOfOrder();
prio(high) sync Test2_Msg2();
prio(high) sync Test2_FirstUrgent();
prio(high) sync Test2_SecondUrgent();
sync Test3_Start() returns (uint32_t result);
rpc Test3_InnerEvent() returns (uint32_t result);
intr Test4_Start() returns (uint32_t result);
rpc Test4_Inner() returns (uint32_t result);
prio(high) sync Test3_InnerEvent() returns (uint32_t result);
child:
async Start();
rpc Test1_InnerQuery() returns (uint32_t result);
rpc Test1_NoReenter() returns (uint32_t result);
rpc Test2_FirstUrgent();
rpc Test2_SecondUrgent();
rpc Test3_WakeUp() returns (uint32_t result);
rpc Test4_WakeUp() returns (uint32_t result);
prio(high) sync Test1_InnerQuery() returns (uint32_t result);
prio(high) sync Test1_NoReenter() returns (uint32_t result);
prio(high) sync Test2_Msg1();
prio(high) sync Test2_Msg3();
prio(high) sync Test3_WakeUp() returns (uint32_t result);
};
} // namespace _ipdltest

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

@ -1,7 +1,7 @@
namespace mozilla {
namespace _ipdltest {
intr protocol PTestUrgency
prio(normal upto high) sync protocol PTestUrgency
{
parent:
sync Test1() returns (uint32_t result);
@ -11,8 +11,8 @@ parent:
child:
async Start();
rpc Reply1() returns (uint32_t result);
rpc Reply2() returns (uint32_t result);
prio(high) sync Reply1() returns (uint32_t result);
prio(high) sync Reply2() returns (uint32_t result);
};
} // namespace _ipdltest

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

@ -0,0 +1,118 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: sw=4 ts=4 et :
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TestHighestPrio.h"
#include "IPDLUnitTests.h" // fail etc.
#if defined(OS_POSIX)
#include <unistd.h>
#else
#include <windows.h>
#endif
namespace mozilla {
namespace _ipdltest {
//-----------------------------------------------------------------------------
// parent
TestHighestPrioParent::TestHighestPrioParent()
: msg_num_(0)
{
MOZ_COUNT_CTOR(TestHighestPrioParent);
}
TestHighestPrioParent::~TestHighestPrioParent()
{
MOZ_COUNT_DTOR(TestHighestPrioParent);
}
void
TestHighestPrioParent::Main()
{
if (!SendStart())
fail("sending Start");
}
bool
TestHighestPrioParent::RecvMsg1()
{
MOZ_ASSERT(msg_num_ == 0);
msg_num_ = 1;
return true;
}
bool
TestHighestPrioParent::RecvMsg2()
{
MOZ_ASSERT(msg_num_ == 1);
msg_num_ = 2;
if (!SendStartInner())
fail("sending StartInner");
return true;
}
bool
TestHighestPrioParent::RecvMsg3()
{
MOZ_ASSERT(msg_num_ == 2);
msg_num_ = 3;
return true;
}
bool
TestHighestPrioParent::RecvMsg4()
{
MOZ_ASSERT(msg_num_ == 3);
msg_num_ = 4;
return true;
}
//-----------------------------------------------------------------------------
// child
TestHighestPrioChild::TestHighestPrioChild()
{
MOZ_COUNT_CTOR(TestHighestPrioChild);
}
TestHighestPrioChild::~TestHighestPrioChild()
{
MOZ_COUNT_DTOR(TestHighestPrioChild);
}
bool
TestHighestPrioChild::RecvStart()
{
if (!SendMsg1())
fail("sending Msg1");
if (!SendMsg2())
fail("sending Msg2");
Close();
return true;
}
bool
TestHighestPrioChild::RecvStartInner()
{
if (!SendMsg3())
fail("sending Msg3");
if (!SendMsg4())
fail("sending Msg4");
return true;
}
} // namespace _ipdltest
} // namespace mozilla

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

@ -0,0 +1,68 @@
#ifndef mozilla__ipdltest_TestHighestPrio_h
#define mozilla__ipdltest_TestHighestPrio_h 1
#include "mozilla/_ipdltest/IPDLUnitTests.h"
#include "mozilla/_ipdltest/PTestHighestPrioParent.h"
#include "mozilla/_ipdltest/PTestHighestPrioChild.h"
namespace mozilla {
namespace _ipdltest {
class TestHighestPrioParent :
public PTestHighestPrioParent
{
public:
TestHighestPrioParent();
virtual ~TestHighestPrioParent();
static bool RunTestInProcesses() { return true; }
static bool RunTestInThreads() { return false; }
void Main();
bool RecvMsg1() MOZ_OVERRIDE;
bool RecvMsg2() MOZ_OVERRIDE;
bool RecvMsg3() MOZ_OVERRIDE;
bool RecvMsg4() MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
{
if (NormalShutdown != why)
fail("unexpected destruction!");
if (msg_num_ != 4)
fail("missed IPC call");
passed("ok");
QuitParent();
}
private:
int msg_num_;
};
class TestHighestPrioChild :
public PTestHighestPrioChild
{
public:
TestHighestPrioChild();
virtual ~TestHighestPrioChild();
bool RecvStart() MOZ_OVERRIDE;
bool RecvStartInner() MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
{
if (NormalShutdown != why)
fail("unexpected destruction!");
QuitChild();
}
};
} // namespace _ipdltest
} // namespace mozilla
#endif // ifndef mozilla__ipdltest_TestHighestPrio_h

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

@ -14,8 +14,6 @@ namespace _ipdltest {
// parent
TestRPCParent::TestRPCParent()
: reentered_(false),
resolved_first_cpow_(false)
{
MOZ_COUNT_CTOR(TestRPCParent);
}
@ -33,11 +31,11 @@ TestRPCParent::Main()
}
bool
TestRPCParent::AnswerTest1_Start(uint32_t* aResult)
TestRPCParent::RecvTest1_Start(uint32_t* aResult)
{
uint32_t result;
if (!CallTest1_InnerQuery(&result))
fail("CallTest1_InnerQuery");
if (!SendTest1_InnerQuery(&result))
fail("SendTest1_InnerQuery");
if (result != 300)
fail("Wrong result (expected 300)");
@ -46,11 +44,11 @@ TestRPCParent::AnswerTest1_Start(uint32_t* aResult)
}
bool
TestRPCParent::AnswerTest1_InnerEvent(uint32_t* aResult)
TestRPCParent::RecvTest1_InnerEvent(uint32_t* aResult)
{
uint32_t result;
if (!CallTest1_NoReenter(&result))
fail("CallTest1_NoReenter");
if (!SendTest1_NoReenter(&result))
fail("SendTest1_NoReenter");
if (result != 400)
fail("Wrong result (expected 400)");
@ -61,65 +59,56 @@ TestRPCParent::AnswerTest1_InnerEvent(uint32_t* aResult)
bool
TestRPCParent::RecvTest2_Start()
{
// Send a CPOW. During this time, we must NOT process the RPC message, as
// we could start receiving CPOW replies out-of-order.
if (!CallTest2_FirstUrgent())
fail("CallTest2_FirstUrgent");
if (!SendTest2_Msg1())
fail("SendTest2_Msg1");
MOZ_ASSERT(!reentered_);
resolved_first_cpow_ = true;
return true;
}
bool
TestRPCParent::AnswerTest2_OutOfOrder()
TestRPCParent::RecvTest2_Msg2()
{
// Send a CPOW. If this RPC call was initiated while waiting for the first
// CPOW to resolve, replies will be processed out of order, and we'll crash.
if (!CallTest2_SecondUrgent())
fail("CallTest2_SecondUrgent");
if (!SendTest2_Msg3())
fail("SendTest2_Msg3");
reentered_ = true;
return true;
}
bool
TestRPCParent::RecvTest2_FirstUrgent()
{
return true;
}
bool
TestRPCParent::RecvTest2_SecondUrgent()
{
return true;
}
bool
TestRPCParent::RecvTest3_Start(uint32_t* aResult)
{
if (!CallTest3_WakeUp(aResult))
fail("CallTest3_WakeUp");
if (!SendTest3_WakeUp(aResult))
fail("SendTest3_WakeUp");
return true;
}
bool
TestRPCParent::AnswerTest3_InnerEvent(uint32_t* aResult)
TestRPCParent::RecvTest3_InnerEvent(uint32_t* aResult)
{
*aResult = 200;
return true;
}
bool
TestRPCParent::AnswerTest4_Start(uint32_t* aResult)
{
if (!CallTest4_WakeUp(aResult))
fail("CallTest4_WakeUp");
return true;
}
bool
TestRPCParent::AnswerTest4_Inner(uint32_t* aResult)
{
*aResult = 700;
return true;
}
//-----------------------------------------------------------------------------
// child
TestRPCChild::TestRPCChild()
: reentered_(false),
resolved_first_cpow_(false)
{
MOZ_COUNT_CTOR(TestRPCChild);
}
@ -133,16 +122,16 @@ bool
TestRPCChild::RecvStart()
{
uint32_t result;
if (!CallTest1_Start(&result))
fail("CallTest1_Start");
if (!SendTest1_Start(&result))
fail("SendTest1_Start");
if (result != 100)
fail("Wrong result (expected 100)");
if (!SendTest2_Start())
fail("SendTest2_Start");
if (!CallTest2_OutOfOrder())
fail("CallTest2_OutOfOrder");
if (!SendTest2_Msg2())
fail("SendTest2_Msg2");
result = 0;
if (!SendTest3_Start(&result))
@ -150,22 +139,16 @@ TestRPCChild::RecvStart()
if (result != 200)
fail("Wrong result (expected 200)");
// See bug 937216 (RPC calls within interrupts).
if (!CallTest4_Start(&result))
fail("SendTest4_Start");
if (result != 700)
fail("Wrong result (expected 700)");
Close();
return true;
}
bool
TestRPCChild::AnswerTest1_InnerQuery(uint32_t* aResult)
TestRPCChild::RecvTest1_InnerQuery(uint32_t* aResult)
{
uint32_t result;
if (!CallTest1_InnerEvent(&result))
fail("CallTest1_InnerEvent");
if (!SendTest1_InnerEvent(&result))
fail("SendTest1_InnerEvent");
if (result != 200)
fail("Wrong result (expected 200)");
@ -174,38 +157,43 @@ TestRPCChild::AnswerTest1_InnerQuery(uint32_t* aResult)
}
bool
TestRPCChild::AnswerTest1_NoReenter(uint32_t* aResult)
TestRPCChild::RecvTest1_NoReenter(uint32_t* aResult)
{
*aResult = 400;
return true;
}
bool
TestRPCChild::AnswerTest2_FirstUrgent()
bool TestRPCChild::RecvTest2_Msg1()
{
MOZ_ASSERT(resolved_first_cpow_);
// Send a CPOW. If this RPC call was initiated while waiting for the first
// CPOW to resolve, replies will be processed out of order, and we'll crash.
if (!SendTest2_SecondUrgent())
fail("SendTest2_SecondUrgent");
reentered_ = true;
return true;
}
bool
TestRPCChild::AnswerTest2_SecondUrgent()
TestRPCChild::RecvTest2_Msg3()
{
// Send a CPOW. During this time, we must NOT process the RPC message, as
// we could start receiving CPOW replies out-of-order.
if (!SendTest2_FirstUrgent())
fail("SendTest2_FirstUrgent");
MOZ_ASSERT(!reentered_);
resolved_first_cpow_ = true;
return true;
}
bool
TestRPCChild::AnswerTest3_WakeUp(uint32_t* aResult)
TestRPCChild::RecvTest3_WakeUp(uint32_t* aResult)
{
if (!CallTest3_InnerEvent(aResult))
fail("CallTest3_InnerEvent");
return true;
}
bool
TestRPCChild::AnswerTest4_WakeUp(uint32_t* aResult)
{
if (!CallTest4_Inner(aResult))
fail("CallTest4_Inner");
if (!SendTest3_InnerEvent(aResult))
fail("SendTest3_InnerEvent");
return true;
}

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

@ -22,30 +22,22 @@ public:
void Main();
bool AnswerTest1_Start(uint32_t* aResult) MOZ_OVERRIDE;
bool AnswerTest1_InnerEvent(uint32_t* aResult) MOZ_OVERRIDE;
bool RecvTest1_Start(uint32_t* aResult) MOZ_OVERRIDE;
bool RecvTest1_InnerEvent(uint32_t* aResult) MOZ_OVERRIDE;
bool RecvTest2_Start() MOZ_OVERRIDE;
bool AnswerTest2_OutOfOrder() MOZ_OVERRIDE;
bool RecvTest2_Msg2() MOZ_OVERRIDE;
bool RecvTest2_FirstUrgent() MOZ_OVERRIDE;
bool RecvTest2_SecondUrgent() MOZ_OVERRIDE;
bool RecvTest3_Start(uint32_t* aResult) MOZ_OVERRIDE;
bool AnswerTest3_InnerEvent(uint32_t* aResult) MOZ_OVERRIDE;
bool AnswerTest4_Start(uint32_t* aResult) MOZ_OVERRIDE;
bool AnswerTest4_Inner(uint32_t* aResult) MOZ_OVERRIDE;
bool RecvTest3_InnerEvent(uint32_t* aResult) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
{
if (NormalShutdown != why)
fail("unexpected destruction!");
if (!reentered_)
fail("never processed raced RPC call!");
if (!resolved_first_cpow_)
fail("never resolved first CPOW!");
passed("ok");
QuitParent();
}
private:
bool reentered_;
bool resolved_first_cpow_;
};
@ -57,12 +49,11 @@ public:
virtual ~TestRPCChild();
bool RecvStart() MOZ_OVERRIDE;
bool AnswerTest1_InnerQuery(uint32_t* aResult) MOZ_OVERRIDE;
bool AnswerTest1_NoReenter(uint32_t* aResult) MOZ_OVERRIDE;
bool AnswerTest2_FirstUrgent() MOZ_OVERRIDE;
bool AnswerTest2_SecondUrgent() MOZ_OVERRIDE;
bool AnswerTest3_WakeUp(uint32_t* aResult) MOZ_OVERRIDE;
bool AnswerTest4_WakeUp(uint32_t* aResult) MOZ_OVERRIDE;
bool RecvTest1_InnerQuery(uint32_t* aResult) MOZ_OVERRIDE;
bool RecvTest1_NoReenter(uint32_t* aResult) MOZ_OVERRIDE;
bool RecvTest2_Msg1() MOZ_OVERRIDE;
bool RecvTest2_Msg3() MOZ_OVERRIDE;
bool RecvTest3_WakeUp(uint32_t* aResult) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
{
@ -70,6 +61,10 @@ public:
fail("unexpected destruction!");
QuitChild();
}
private:
bool reentered_;
bool resolved_first_cpow_;
};

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

@ -48,7 +48,7 @@ TestUrgencyParent::Main()
bool
TestUrgencyParent::RecvTest1(uint32_t *value)
{
if (!CallReply1(value))
if (!SendReply1(value))
fail("sending Reply1");
if (*value != 99)
fail("bad value");
@ -60,7 +60,7 @@ TestUrgencyParent::RecvTest2()
{
uint32_t value;
inreply_ = true;
if (!CallReply2(&value))
if (!SendReply2(&value))
fail("sending Reply2");
inreply_ = false;
if (value != 500)
@ -130,10 +130,10 @@ TestUrgencyChild::RecvStart()
}
bool
TestUrgencyChild::AnswerReply1(uint32_t *reply)
TestUrgencyChild::RecvReply1(uint32_t *reply)
{
if (test_ != kFirstTestBegin)
fail("wrong test # in AnswerReply1");
fail("wrong test # in RecvReply1");
*reply = 99;
test_ = kFirstTestGotReply;
@ -141,10 +141,10 @@ TestUrgencyChild::AnswerReply1(uint32_t *reply)
}
bool
TestUrgencyChild::AnswerReply2(uint32_t *reply)
TestUrgencyChild::RecvReply2(uint32_t *reply)
{
if (test_ != kSecondTestBegin)
fail("wrong test # in AnswerReply2");
fail("wrong test # in RecvReply2");
// sleep for 5 seconds so the parent process tries to deliver more messages.
Sleep(5000);

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

@ -52,10 +52,8 @@ public:
virtual ~TestUrgencyChild();
bool RecvStart();
bool AnswerReply1(uint32_t *reply);
bool AnswerReply2(uint32_t *reply);
bool AnswerTest4_Reenter();
bool AnswerFinalTest_Hang();
bool RecvReply1(uint32_t *reply);
bool RecvReply2(uint32_t *reply);
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
{

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

@ -22,6 +22,7 @@ SOURCES += [
'TestDesc.cpp',
'TestFailedCtor.cpp',
'TestHangs.cpp',
'TestHighestPrio.cpp',
'TestInterruptErrorCleanup.cpp',
'TestInterruptRaces.cpp',
'TestInterruptShutdownRace.cpp',
@ -82,6 +83,7 @@ IPDL_SOURCES += [
'PTestFailedCtorSubsub.ipdl',
'PTestHandle.ipdl',
'PTestHangs.ipdl',
'PTestHighestPrio.ipdl',
'PTestIndirectProtocolParam.ipdlh',
'PTestIndirectProtocolParamFirst.ipdl',
'PTestIndirectProtocolParamManage.ipdl',

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

@ -9,7 +9,7 @@ include protocol PTestShellCommand;
namespace mozilla {
namespace ipc {
intr protocol PTestShell
async protocol PTestShell
{
manager PContent;

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

@ -35,91 +35,91 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
/*** IPC handlers ***/
bool AnswerPreventExtensions(const uint64_t &objId, ReturnStatus *rs) {
return Answer::AnswerPreventExtensions(ObjectId::deserialize(objId), rs);
bool RecvPreventExtensions(const uint64_t &objId, ReturnStatus *rs) {
return Answer::RecvPreventExtensions(ObjectId::deserialize(objId), rs);
}
bool AnswerGetPropertyDescriptor(const uint64_t &objId, const JSIDVariant &id,
bool RecvGetPropertyDescriptor(const uint64_t &objId, const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out) {
return Answer::AnswerGetPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
return Answer::RecvGetPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
}
bool AnswerGetOwnPropertyDescriptor(const uint64_t &objId,
bool RecvGetOwnPropertyDescriptor(const uint64_t &objId,
const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out) {
return Answer::AnswerGetOwnPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
return Answer::RecvGetOwnPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
}
bool AnswerDefineProperty(const uint64_t &objId, const JSIDVariant &id,
bool RecvDefineProperty(const uint64_t &objId, const JSIDVariant &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs) {
return Answer::AnswerDefineProperty(ObjectId::deserialize(objId), id, flags, rs);
return Answer::RecvDefineProperty(ObjectId::deserialize(objId), id, flags, rs);
}
bool AnswerDelete(const uint64_t &objId, const JSIDVariant &id,
bool RecvDelete(const uint64_t &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *success) {
return Answer::AnswerDelete(ObjectId::deserialize(objId), id, rs, success);
return Answer::RecvDelete(ObjectId::deserialize(objId), id, rs, success);
}
bool AnswerHas(const uint64_t &objId, const JSIDVariant &id,
bool RecvHas(const uint64_t &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp) {
return Answer::AnswerHas(ObjectId::deserialize(objId), id, rs, bp);
return Answer::RecvHas(ObjectId::deserialize(objId), id, rs, bp);
}
bool AnswerHasOwn(const uint64_t &objId, const JSIDVariant &id,
bool RecvHasOwn(const uint64_t &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp) {
return Answer::AnswerHasOwn(ObjectId::deserialize(objId), id, rs, bp);
return Answer::RecvHasOwn(ObjectId::deserialize(objId), id, rs, bp);
}
bool AnswerGet(const uint64_t &objId, const ObjectVariant &receiverVar,
bool RecvGet(const uint64_t &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id,
ReturnStatus *rs, JSVariant *result) {
return Answer::AnswerGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
return Answer::RecvGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
}
bool AnswerSet(const uint64_t &objId, const ObjectVariant &receiverVar,
bool RecvSet(const uint64_t &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const bool &strict,
const JSVariant &value, ReturnStatus *rs, JSVariant *result) {
return Answer::AnswerSet(ObjectId::deserialize(objId), receiverVar, id, strict, value, rs, result);
return Answer::RecvSet(ObjectId::deserialize(objId), receiverVar, id, strict, value, rs, result);
}
bool AnswerIsExtensible(const uint64_t &objId, ReturnStatus *rs,
bool RecvIsExtensible(const uint64_t &objId, ReturnStatus *rs,
bool *result) {
return Answer::AnswerIsExtensible(ObjectId::deserialize(objId), rs, result);
return Answer::RecvIsExtensible(ObjectId::deserialize(objId), rs, result);
}
bool AnswerCallOrConstruct(const uint64_t &objId, const nsTArray<JSParam> &argv,
bool RecvCallOrConstruct(const uint64_t &objId, const nsTArray<JSParam> &argv,
const bool &construct, ReturnStatus *rs, JSVariant *result,
nsTArray<JSParam> *outparams) {
return Answer::AnswerCallOrConstruct(ObjectId::deserialize(objId), argv, construct, rs, result, outparams);
return Answer::RecvCallOrConstruct(ObjectId::deserialize(objId), argv, construct, rs, result, outparams);
}
bool AnswerHasInstance(const uint64_t &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
return Answer::AnswerHasInstance(ObjectId::deserialize(objId), v, rs, bp);
bool RecvHasInstance(const uint64_t &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
return Answer::RecvHasInstance(ObjectId::deserialize(objId), v, rs, bp);
}
bool AnswerObjectClassIs(const uint64_t &objId, const uint32_t &classValue,
bool RecvObjectClassIs(const uint64_t &objId, const uint32_t &classValue,
bool *result) {
return Answer::AnswerObjectClassIs(ObjectId::deserialize(objId), classValue, result);
return Answer::RecvObjectClassIs(ObjectId::deserialize(objId), classValue, result);
}
bool AnswerClassName(const uint64_t &objId, nsString *result) {
return Answer::AnswerClassName(ObjectId::deserialize(objId), result);
bool RecvClassName(const uint64_t &objId, nsString *result) {
return Answer::RecvClassName(ObjectId::deserialize(objId), result);
}
bool AnswerRegExpToShared(const uint64_t &objId, ReturnStatus *rs, nsString *source, uint32_t *flags) {
return Answer::AnswerRegExpToShared(ObjectId::deserialize(objId), rs, source, flags);
bool RecvRegExpToShared(const uint64_t &objId, ReturnStatus *rs, nsString *source, uint32_t *flags) {
return Answer::RecvRegExpToShared(ObjectId::deserialize(objId), rs, source, flags);
}
bool AnswerGetPropertyNames(const uint64_t &objId, const uint32_t &flags,
bool RecvGetPropertyNames(const uint64_t &objId, const uint32_t &flags,
ReturnStatus *rs, nsTArray<nsString> *names) {
return Answer::AnswerGetPropertyNames(ObjectId::deserialize(objId), flags, rs, names);
return Answer::RecvGetPropertyNames(ObjectId::deserialize(objId), flags, rs, names);
}
bool AnswerInstanceOf(const uint64_t &objId, const JSIID &iid,
bool RecvInstanceOf(const uint64_t &objId, const JSIID &iid,
ReturnStatus *rs, bool *instanceof) {
return Answer::AnswerInstanceOf(ObjectId::deserialize(objId), iid, rs, instanceof);
return Answer::RecvInstanceOf(ObjectId::deserialize(objId), iid, rs, instanceof);
}
bool AnswerDOMInstanceOf(const uint64_t &objId, const int &prototypeID, const int &depth,
bool RecvDOMInstanceOf(const uint64_t &objId, const int &prototypeID, const int &depth,
ReturnStatus *rs, bool *instanceof) {
return Answer::AnswerDOMInstanceOf(ObjectId::deserialize(objId), prototypeID, depth, rs, instanceof);
return Answer::RecvDOMInstanceOf(ObjectId::deserialize(objId), prototypeID, depth, rs, instanceof);
}
bool AnswerIsCallable(const uint64_t &objId, bool *result) {
return Answer::AnswerIsCallable(ObjectId::deserialize(objId), result);
bool RecvIsCallable(const uint64_t &objId, bool *result) {
return Answer::RecvIsCallable(ObjectId::deserialize(objId), result);
}
bool AnswerIsConstructor(const uint64_t &objId, bool *result) {
return Answer::AnswerIsConstructor(ObjectId::deserialize(objId), result);
bool RecvIsConstructor(const uint64_t &objId, bool *result) {
return Answer::RecvIsConstructor(ObjectId::deserialize(objId), result);
}
bool RecvDropObject(const uint64_t &objId) {
@ -131,93 +131,93 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
bool SendDropObject(const ObjectId &objId) {
return Base::SendDropObject(objId.serialize());
}
bool CallPreventExtensions(const ObjectId &objId, ReturnStatus *rs) {
return Base::CallPreventExtensions(objId.serialize(), rs);
bool SendPreventExtensions(const ObjectId &objId, ReturnStatus *rs) {
return Base::SendPreventExtensions(objId.serialize(), rs);
}
bool CallGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
bool SendGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out) {
return Base::CallGetPropertyDescriptor(objId.serialize(), id, rs, out);
return Base::SendGetPropertyDescriptor(objId.serialize(), id, rs, out);
}
bool CallGetOwnPropertyDescriptor(const ObjectId &objId,
bool SendGetOwnPropertyDescriptor(const ObjectId &objId,
const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out) {
return Base::CallGetOwnPropertyDescriptor(objId.serialize(), id, rs, out);
return Base::SendGetOwnPropertyDescriptor(objId.serialize(), id, rs, out);
}
bool CallDefineProperty(const ObjectId &objId, const JSIDVariant &id,
bool SendDefineProperty(const ObjectId &objId, const JSIDVariant &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs) {
return Base::CallDefineProperty(objId.serialize(), id, flags, rs);
return Base::SendDefineProperty(objId.serialize(), id, flags, rs);
}
bool CallDelete(const ObjectId &objId, const JSIDVariant &id,
bool SendDelete(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *success) {
return Base::CallDelete(objId.serialize(), id, rs, success);
return Base::SendDelete(objId.serialize(), id, rs, success);
}
bool CallHas(const ObjectId &objId, const JSIDVariant &id,
bool SendHas(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp) {
return Base::CallHas(objId.serialize(), id, rs, bp);
return Base::SendHas(objId.serialize(), id, rs, bp);
}
bool CallHasOwn(const ObjectId &objId, const JSIDVariant &id,
bool SendHasOwn(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp) {
return Base::CallHasOwn(objId.serialize(), id, rs, bp);
return Base::SendHasOwn(objId.serialize(), id, rs, bp);
}
bool CallGet(const ObjectId &objId, const ObjectVariant &receiverVar,
bool SendGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id,
ReturnStatus *rs, JSVariant *result) {
return Base::CallGet(objId.serialize(), receiverVar, id, rs, result);
return Base::SendGet(objId.serialize(), receiverVar, id, rs, result);
}
bool CallSet(const ObjectId &objId, const ObjectVariant &receiverVar,
bool SendSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const bool &strict,
const JSVariant &value, ReturnStatus *rs, JSVariant *result) {
return Base::CallSet(objId.serialize(), receiverVar, id, strict, value, rs, result);
return Base::SendSet(objId.serialize(), receiverVar, id, strict, value, rs, result);
}
bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool SendIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool *result) {
return Base::CallIsExtensible(objId.serialize(), rs, result);
return Base::SendIsExtensible(objId.serialize(), rs, result);
}
bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
bool SendCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
const bool &construct, ReturnStatus *rs, JSVariant *result,
nsTArray<JSParam> *outparams) {
return Base::CallCallOrConstruct(objId.serialize(), argv, construct, rs, result, outparams);
return Base::SendCallOrConstruct(objId.serialize(), argv, construct, rs, result, outparams);
}
bool CallHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
return Base::CallHasInstance(objId.serialize(), v, rs, bp);
bool SendHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
return Base::SendHasInstance(objId.serialize(), v, rs, bp);
}
bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool SendObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result) {
return Base::CallObjectClassIs(objId.serialize(), classValue, result);
return Base::SendObjectClassIs(objId.serialize(), classValue, result);
}
bool CallClassName(const ObjectId &objId, nsString *result) {
return Base::CallClassName(objId.serialize(), result);
bool SendClassName(const ObjectId &objId, nsString *result) {
return Base::SendClassName(objId.serialize(), result);
}
bool CallRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
nsString *source, uint32_t *flags) {
return Base::CallRegExpToShared(objId.serialize(), rs, source, flags);
return Base::SendRegExpToShared(objId.serialize(), rs, source, flags);
}
bool CallGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
bool SendGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
ReturnStatus *rs, nsTArray<nsString> *names) {
return Base::CallGetPropertyNames(objId.serialize(), flags, rs, names);
return Base::SendGetPropertyNames(objId.serialize(), flags, rs, names);
}
bool CallInstanceOf(const ObjectId &objId, const JSIID &iid,
bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
ReturnStatus *rs, bool *instanceof) {
return Base::CallInstanceOf(objId.serialize(), iid, rs, instanceof);
return Base::SendInstanceOf(objId.serialize(), iid, rs, instanceof);
}
bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
bool SendDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
ReturnStatus *rs, bool *instanceof) {
return Base::CallDOMInstanceOf(objId.serialize(), prototypeID, depth, rs, instanceof);
return Base::SendDOMInstanceOf(objId.serialize(), prototypeID, depth, rs, instanceof);
}
bool CallIsCallable(const ObjectId &objId, bool *result) {
return Base::CallIsCallable(objId.serialize(), result);
bool SendIsCallable(const ObjectId &objId, bool *result) {
return Base::SendIsCallable(objId.serialize(), result);
}
bool CallIsConstructor(const ObjectId &objId, bool *result) {
return Base::CallIsConstructor(objId.serialize(), result);
bool SendIsConstructor(const ObjectId &objId, bool *result) {
return Base::SendIsConstructor(objId.serialize(), result);
}
/* The following code is needed to suppress a bogus MSVC warning (C4250). */

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

@ -15,7 +15,7 @@ using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
namespace mozilla {
namespace jsipc {
intr protocol PJavaScript
prio(normal upto high) sync protocol PJavaScript
{
manager PContent or PContentBridge;
@ -24,30 +24,30 @@ both:
async DropObject(uint64_t objId);
// These roughly map to the ProxyHandler hooks that CPOWs need.
rpc PreventExtensions(uint64_t objId) returns (ReturnStatus rs);
rpc GetPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
rpc GetOwnPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
rpc DefineProperty(uint64_t objId, JSIDVariant id, PPropertyDescriptor descriptor) returns (ReturnStatus rs);
rpc Delete(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool successful);
prio(high) sync PreventExtensions(uint64_t objId) returns (ReturnStatus rs);
prio(high) sync GetPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
prio(high) sync GetOwnPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
prio(high) sync DefineProperty(uint64_t objId, JSIDVariant id, PPropertyDescriptor descriptor) returns (ReturnStatus rs);
prio(high) sync Delete(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool successful);
rpc Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
rpc HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
rpc Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
rpc Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
prio(high) sync Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
prio(high) sync HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
prio(high) sync Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
prio(high) sync Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
rpc IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
rpc CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
rpc HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
rpc ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
rpc ClassName(uint64_t objId) returns (nsString name);
rpc RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
prio(high) sync IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
prio(high) sync CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
prio(high) sync HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
prio(high) sync ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
prio(high) sync ClassName(uint64_t objId) returns (nsString name);
prio(high) sync RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
rpc GetPropertyNames(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, nsString[] names);
rpc InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
rpc DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
prio(high) sync GetPropertyNames(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, nsString[] names);
prio(high) sync InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
prio(high) sync DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
rpc IsCallable(uint64_t objId) returns (bool result);
rpc IsConstructor(uint64_t objId) returns (bool result);
prio(high) sync IsCallable(uint64_t objId) returns (bool result);
prio(high) sync IsConstructor(uint64_t objId) returns (bool result);
parent:
async __delete__();

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

@ -58,7 +58,7 @@ WrapperAnswer::ok(ReturnStatus *rs)
}
bool
WrapperAnswer::AnswerPreventExtensions(const ObjectId &objId, ReturnStatus *rs)
WrapperAnswer::RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -87,8 +87,8 @@ EmptyDesc(PPropertyDescriptor *desc)
}
bool
WrapperAnswer::AnswerGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
ReturnStatus *rs, PPropertyDescriptor *out)
WrapperAnswer::RecvGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
ReturnStatus *rs, PPropertyDescriptor *out)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -121,8 +121,8 @@ WrapperAnswer::AnswerGetPropertyDescriptor(const ObjectId &objId, const JSIDVari
}
bool
WrapperAnswer::AnswerGetOwnPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
ReturnStatus *rs, PPropertyDescriptor *out)
WrapperAnswer::RecvGetOwnPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
ReturnStatus *rs, PPropertyDescriptor *out)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -155,8 +155,8 @@ WrapperAnswer::AnswerGetOwnPropertyDescriptor(const ObjectId &objId, const JSIDV
}
bool
WrapperAnswer::AnswerDefineProperty(const ObjectId &objId, const JSIDVariant &idVar,
const PPropertyDescriptor &descriptor, ReturnStatus *rs)
WrapperAnswer::RecvDefineProperty(const ObjectId &objId, const JSIDVariant &idVar,
const PPropertyDescriptor &descriptor, ReturnStatus *rs)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -193,8 +193,8 @@ WrapperAnswer::AnswerDefineProperty(const ObjectId &objId, const JSIDVariant &id
}
bool
WrapperAnswer::AnswerDelete(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
bool *success)
WrapperAnswer::RecvDelete(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
bool *success)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -220,7 +220,7 @@ WrapperAnswer::AnswerDelete(const ObjectId &objId, const JSIDVariant &idVar, Ret
}
bool
WrapperAnswer::AnswerHas(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs, bool *bp)
WrapperAnswer::RecvHas(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs, bool *bp)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -248,8 +248,8 @@ WrapperAnswer::AnswerHas(const ObjectId &objId, const JSIDVariant &idVar, Return
}
bool
WrapperAnswer::AnswerHasOwn(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
bool *bp)
WrapperAnswer::RecvHasOwn(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
bool *bp)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -277,8 +277,8 @@ WrapperAnswer::AnswerHasOwn(const ObjectId &objId, const JSIDVariant &idVar, Ret
}
bool
WrapperAnswer::AnswerGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &idVar, ReturnStatus *rs, JSVariant *result)
WrapperAnswer::RecvGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &idVar, ReturnStatus *rs, JSVariant *result)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -314,9 +314,9 @@ WrapperAnswer::AnswerGet(const ObjectId &objId, const ObjectVariant &receiverVar
}
bool
WrapperAnswer::AnswerSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &idVar, const bool &strict, const JSVariant &value,
ReturnStatus *rs, JSVariant *result)
WrapperAnswer::RecvSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &idVar, const bool &strict, const JSVariant &value,
ReturnStatus *rs, JSVariant *result)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -357,7 +357,7 @@ WrapperAnswer::AnswerSet(const ObjectId &objId, const ObjectVariant &receiverVar
}
bool
WrapperAnswer::AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs, bool *result)
WrapperAnswer::RecvIsExtensible(const ObjectId &objId, ReturnStatus *rs, bool *result)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -381,12 +381,12 @@ WrapperAnswer::AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs, bool
}
bool
WrapperAnswer::AnswerCallOrConstruct(const ObjectId &objId,
const nsTArray<JSParam> &argv,
const bool &construct,
ReturnStatus *rs,
JSVariant *result,
nsTArray<JSParam> *outparams)
WrapperAnswer::RecvCallOrConstruct(const ObjectId &objId,
const nsTArray<JSParam> &argv,
const bool &construct,
ReturnStatus *rs,
JSVariant *result,
nsTArray<JSParam> *outparams)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -488,7 +488,7 @@ WrapperAnswer::AnswerCallOrConstruct(const ObjectId &objId,
}
bool
WrapperAnswer::AnswerHasInstance(const ObjectId &objId, const JSVariant &vVar, ReturnStatus *rs, bool *bp)
WrapperAnswer::RecvHasInstance(const ObjectId &objId, const JSVariant &vVar, ReturnStatus *rs, bool *bp)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -512,8 +512,8 @@ WrapperAnswer::AnswerHasInstance(const ObjectId &objId, const JSVariant &vVar, R
}
bool
WrapperAnswer::AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result)
WrapperAnswer::RecvObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -534,7 +534,7 @@ WrapperAnswer::AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classV
}
bool
WrapperAnswer::AnswerClassName(const ObjectId &objId, nsString *name)
WrapperAnswer::RecvClassName(const ObjectId &objId, nsString *name)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -554,8 +554,8 @@ WrapperAnswer::AnswerClassName(const ObjectId &objId, nsString *name)
}
bool
WrapperAnswer::AnswerRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
nsString *source, uint32_t *flags)
WrapperAnswer::RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
nsString *source, uint32_t *flags)
{
AutoSafeJSContext cx;
RootedObject obj(cx, findObjectById(cx, objId));
@ -579,8 +579,8 @@ WrapperAnswer::AnswerRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
}
bool
WrapperAnswer::AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
ReturnStatus *rs, nsTArray<nsString> *names)
WrapperAnswer::RecvGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
ReturnStatus *rs, nsTArray<nsString> *names)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -609,8 +609,8 @@ WrapperAnswer::AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &fla
}
bool
WrapperAnswer::AnswerInstanceOf(const ObjectId &objId, const JSIID &iid, ReturnStatus *rs,
bool *instanceof)
WrapperAnswer::RecvInstanceOf(const ObjectId &objId, const JSIID &iid, ReturnStatus *rs,
bool *instanceof)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -636,8 +636,8 @@ WrapperAnswer::AnswerInstanceOf(const ObjectId &objId, const JSIID &iid, ReturnS
}
bool
WrapperAnswer::AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID,
const int &depth, ReturnStatus *rs, bool *instanceof)
WrapperAnswer::RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID,
const int &depth, ReturnStatus *rs, bool *instanceof)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -661,7 +661,7 @@ WrapperAnswer::AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID
}
bool
WrapperAnswer::AnswerIsCallable(const ObjectId &objId, bool *result)
WrapperAnswer::RecvIsCallable(const ObjectId &objId, bool *result)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
@ -681,7 +681,7 @@ WrapperAnswer::AnswerIsCallable(const ObjectId &objId, bool *result)
}
bool
WrapperAnswer::AnswerIsConstructor(const ObjectId &objId, bool *result)
WrapperAnswer::RecvIsConstructor(const ObjectId &objId, bool *result)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);

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

@ -18,51 +18,51 @@ class WrapperAnswer : public virtual JavaScriptShared
public:
explicit WrapperAnswer(JSRuntime *rt) : JavaScriptShared(rt) {}
bool AnswerPreventExtensions(const ObjectId &objId, ReturnStatus *rs);
bool AnswerGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out);
bool AnswerGetOwnPropertyDescriptor(const ObjectId &objId,
const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out);
bool AnswerDefineProperty(const ObjectId &objId, const JSIDVariant &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs);
bool AnswerDelete(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *success);
bool RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs);
bool RecvGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out);
bool RecvGetOwnPropertyDescriptor(const ObjectId &objId,
const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out);
bool RecvDefineProperty(const ObjectId &objId, const JSIDVariant &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs);
bool RecvDelete(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *success);
bool AnswerHas(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp);
bool AnswerHasOwn(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp);
bool AnswerGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id,
ReturnStatus *rs, JSVariant *result);
bool AnswerSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const bool &strict,
const JSVariant &value, ReturnStatus *rs, JSVariant *result);
bool RecvHas(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp);
bool RecvHasOwn(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp);
bool RecvGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id,
ReturnStatus *rs, JSVariant *result);
bool RecvSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const bool &strict,
const JSVariant &value, ReturnStatus *rs, JSVariant *result);
bool AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool *result);
bool AnswerCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
const bool &construct, ReturnStatus *rs, JSVariant *result,
nsTArray<JSParam> *outparams);
bool AnswerHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp);
bool AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result);
bool AnswerClassName(const ObjectId &objId, nsString *result);
bool AnswerRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
bool RecvIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool *result);
bool RecvCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
const bool &construct, ReturnStatus *rs, JSVariant *result,
nsTArray<JSParam> *outparams);
bool RecvHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp);
bool RecvObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result);
bool RecvClassName(const ObjectId &objId, nsString *result);
bool RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
bool AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
ReturnStatus *rs, nsTArray<nsString> *names);
bool AnswerInstanceOf(const ObjectId &objId, const JSIID &iid,
ReturnStatus *rs, bool *instanceof);
bool AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
ReturnStatus *rs, bool *instanceof);
bool RecvGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
ReturnStatus *rs, nsTArray<nsString> *names);
bool RecvInstanceOf(const ObjectId &objId, const JSIID &iid,
ReturnStatus *rs, bool *instanceof);
bool RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
ReturnStatus *rs, bool *instanceof);
bool AnswerIsCallable(const ObjectId &objId, bool *result);
bool AnswerIsConstructor(const ObjectId &objId, bool *result);
bool RecvIsCallable(const ObjectId &objId, bool *result);
bool RecvIsConstructor(const ObjectId &objId, bool *result);
bool RecvDropObject(const ObjectId &objId);

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

@ -124,7 +124,7 @@ WrapperOwner::preventExtensions(JSContext *cx, HandleObject proxy)
ObjectId objId = idOf(proxy);
ReturnStatus status;
if (!CallPreventExtensions(objId, &status))
if (!SendPreventExtensions(objId, &status))
return ipcfail(cx);
LOG_STACK();
@ -151,7 +151,7 @@ WrapperOwner::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId
ReturnStatus status;
PPropertyDescriptor result;
if (!CallGetPropertyDescriptor(objId, idVar, &status, &result))
if (!SendGetPropertyDescriptor(objId, idVar, &status, &result))
return ipcfail(cx);
LOG_STACK();
@ -181,7 +181,7 @@ WrapperOwner::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, Handle
ReturnStatus status;
PPropertyDescriptor result;
if (!CallGetOwnPropertyDescriptor(objId, idVar, &status, &result))
if (!SendGetOwnPropertyDescriptor(objId, idVar, &status, &result))
return ipcfail(cx);
LOG_STACK();
@ -214,7 +214,7 @@ WrapperOwner::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
return false;
ReturnStatus status;
if (!CallDefineProperty(objId, idVar, descriptor, &status))
if (!SendDefineProperty(objId, idVar, descriptor, &status))
return ipcfail(cx);
LOG_STACK();
@ -251,7 +251,7 @@ WrapperOwner::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
return false;
ReturnStatus status;
if (!CallDelete(objId, idVar, &status, bp))
if (!SendDelete(objId, idVar, &status, bp))
return ipcfail(cx);
LOG_STACK();
@ -287,7 +287,7 @@ WrapperOwner::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
return false;
ReturnStatus status;
if (!CallHas(objId, idVar, &status, bp))
if (!SendHas(objId, idVar, &status, bp))
return ipcfail(cx);
LOG_STACK();
@ -311,7 +311,7 @@ WrapperOwner::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
return false;
ReturnStatus status;
if (!CallHasOwn(objId, idVar, &status, bp))
if (!SendHasOwn(objId, idVar, &status, bp))
return ipcfail(cx);
LOG_STACK();
@ -396,7 +396,7 @@ WrapperOwner::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
JSVariant val;
ReturnStatus status;
if (!CallGet(objId, receiverVar, idVar, &status, &val))
if (!SendGet(objId, receiverVar, idVar, &status, &val))
return ipcfail(cx);
LOG_STACK();
@ -451,7 +451,7 @@ WrapperOwner::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiv
ReturnStatus status;
JSVariant result;
if (!CallSet(objId, receiverVar, idVar, strict, val, &status, &result))
if (!SendSet(objId, receiverVar, idVar, strict, val, &status, &result))
return ipcfail(cx);
LOG_STACK();
@ -486,7 +486,7 @@ WrapperOwner::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
ObjectId objId = idOf(proxy);
ReturnStatus status;
if (!CallIsExtensible(objId, &status, extensible))
if (!SendIsExtensible(objId, &status, extensible))
return ipcfail(cx);
LOG_STACK();
@ -550,7 +550,7 @@ WrapperOwner::callOrConstruct(JSContext *cx, HandleObject proxy, const CallArgs
JSVariant result;
ReturnStatus status;
InfallibleTArray<JSParam> outparams;
if (!CallCallOrConstruct(objId, vals, construct, &status, &result, &outparams))
if (!SendCallOrConstruct(objId, vals, construct, &status, &result, &outparams))
return ipcfail(cx);
LOG_STACK();
@ -600,7 +600,7 @@ WrapperOwner::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue
ReturnStatus status;
JSVariant result;
if (!CallHasInstance(objId, vVar, &status, bp))
if (!SendHasInstance(objId, vVar, &status, bp))
return ipcfail(cx);
LOG_STACK();
@ -622,7 +622,7 @@ WrapperOwner::objectClassIs(JSContext *cx, HandleObject proxy, js::ESClassValue
// This function is assumed infallible, so we just return false if the IPC
// channel fails.
bool result;
if (!CallObjectClassIs(objId, classValue, &result))
if (!SendObjectClassIs(objId, classValue, &result))
return false;
LOG_STACK();
@ -645,7 +645,7 @@ WrapperOwner::className(JSContext *cx, HandleObject proxy)
ObjectId objId = idOf(proxy);
nsString name;
if (!CallClassName(objId, &name))
if (!SendClassName(objId, &name))
return "<error>";
LOG_STACK();
@ -667,7 +667,7 @@ WrapperOwner::regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g)
ReturnStatus status;
nsString source;
unsigned flags = 0;
if (!CallRegExpToShared(objId, &status, &source, &flags))
if (!SendRegExpToShared(objId, &status, &source, &flags))
return ipcfail(cx);
LOG_STACK();
@ -711,7 +711,7 @@ WrapperOwner::isCallable(JSObject *obj)
ObjectId objId = idOf(obj);
bool callable = false;
if (!CallIsCallable(objId, &callable)) {
if (!SendIsCallable(objId, &callable)) {
NS_WARNING("IPC isCallable() failed");
return false;
}
@ -734,7 +734,7 @@ WrapperOwner::isConstructor(JSObject *obj)
ObjectId objId = idOf(obj);
bool constructor = false;
if (!CallIsConstructor(objId, &constructor)) {
if (!SendIsConstructor(objId, &constructor)) {
NS_WARNING("IPC isConstructor() failed");
return false;
}
@ -777,7 +777,7 @@ WrapperOwner::getPropertyNames(JSContext *cx, HandleObject proxy, uint32_t flags
ReturnStatus status;
InfallibleTArray<nsString> names;
if (!CallGetPropertyNames(objId, flags, &status, &names))
if (!SendGetPropertyNames(objId, flags, &status, &names))
return ipcfail(cx);
LOG_STACK();
@ -841,7 +841,7 @@ WrapperOwner::instanceOf(JSObject *obj, const nsID *id, bool *bp)
ConvertID(*id, &iid);
ReturnStatus status;
if (!CallInstanceOf(objId, iid, &status, bp))
if (!SendInstanceOf(objId, iid, &status, bp))
return NS_ERROR_UNEXPECTED;
if (status.type() != ReturnStatus::TReturnSuccess)
@ -856,7 +856,7 @@ WrapperOwner::domInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int d
ObjectId objId = idOf(obj);
ReturnStatus status;
if (!CallDOMInstanceOf(objId, prototypeID, depth, &status, bp))
if (!SendDOMInstanceOf(objId, prototypeID, depth, &status, bp))
return ipcfail(cx);
LOG_STACK();

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

@ -107,53 +107,53 @@ class WrapperOwner : public virtual JavaScriptShared
/*** Dummy call handlers ***/
public:
virtual bool SendDropObject(const ObjectId &objId) = 0;
virtual bool CallPreventExtensions(const ObjectId &objId, ReturnStatus *rs) = 0;
virtual bool CallGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
virtual bool SendPreventExtensions(const ObjectId &objId, ReturnStatus *rs) = 0;
virtual bool SendGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out) = 0;
virtual bool CallGetOwnPropertyDescriptor(const ObjectId &objId,
virtual bool SendGetOwnPropertyDescriptor(const ObjectId &objId,
const JSIDVariant &id,
ReturnStatus *rs,
PPropertyDescriptor *out) = 0;
virtual bool CallDefineProperty(const ObjectId &objId, const JSIDVariant &id,
virtual bool SendDefineProperty(const ObjectId &objId, const JSIDVariant &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs) = 0;
virtual bool CallDelete(const ObjectId &objId, const JSIDVariant &id,
virtual bool SendDelete(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *success) = 0;
virtual bool CallHas(const ObjectId &objId, const JSIDVariant &id,
virtual bool SendHas(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp) = 0;
virtual bool CallHasOwn(const ObjectId &objId, const JSIDVariant &id,
virtual bool SendHasOwn(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *bp) = 0;
virtual bool CallGet(const ObjectId &objId, const ObjectVariant &receiverVar,
virtual bool SendGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id,
ReturnStatus *rs, JSVariant *result) = 0;
virtual bool CallSet(const ObjectId &objId, const ObjectVariant &receiverVar,
virtual bool SendSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const bool &strict,
const JSVariant &value, ReturnStatus *rs, JSVariant *result) = 0;
virtual bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
virtual bool SendIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool *result) = 0;
virtual bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
virtual bool SendCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
const bool &construct, ReturnStatus *rs, JSVariant *result,
nsTArray<JSParam> *outparams) = 0;
virtual bool CallHasInstance(const ObjectId &objId, const JSVariant &v,
virtual bool SendHasInstance(const ObjectId &objId, const JSVariant &v,
ReturnStatus *rs, bool *bp) = 0;
virtual bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
virtual bool SendObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result) = 0;
virtual bool CallClassName(const ObjectId &objId, nsString *result) = 0;
virtual bool CallRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source,
virtual bool SendClassName(const ObjectId &objId, nsString *result) = 0;
virtual bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source,
uint32_t *flags) = 0;
virtual bool CallGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
virtual bool SendGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
ReturnStatus *rs, nsTArray<nsString> *names) = 0;
virtual bool CallInstanceOf(const ObjectId &objId, const JSIID &iid,
virtual bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
ReturnStatus *rs, bool *instanceof) = 0;
virtual bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
virtual bool SendDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
ReturnStatus *rs, bool *instanceof) = 0;
virtual bool CallIsCallable(const ObjectId &objId, bool *result) = 0;
virtual bool CallIsConstructor(const ObjectId &objId, bool *result) = 0;
virtual bool SendIsCallable(const ObjectId &objId, bool *result) = 0;
virtual bool SendIsConstructor(const ObjectId &objId, bool *result) = 0;
};
bool

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

@ -4333,7 +4333,7 @@ inline static mozilla::HangMonitor::ActivityType ActivityTypeForMessage(UINT msg
// and http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx
LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
MOZ_RELEASE_ASSERT(!ipc::ProcessingUrgentMessages());
MOZ_RELEASE_ASSERT(!ipc::ParentProcessIsBlocked());
HangMonitor::NotifyActivity(ActivityTypeForMessage(msg));

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

@ -147,7 +147,7 @@ ScreenProxy::EnsureCacheIsValid()
// Kick off a synchronous IPC call to the parent to get the
// most up-to-date information.
ScreenDetails details;
unused << mScreenManager->CallScreenRefresh(mId, &details, &success);
unused << mScreenManager->SendScreenRefresh(mId, &details, &success);
if (!success) {
NS_WARNING("Updating a ScreenProxy in the child process failed on parent side.");
return false;

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

@ -28,7 +28,7 @@ nsScreenManagerProxy::nsScreenManagerProxy()
, mCacheWillInvalidate(false)
{
bool success = false;
unused << ContentChild::GetSingleton()->CallPScreenManagerConstructor(
unused << ContentChild::GetSingleton()->SendPScreenManagerConstructor(
this,
&mNumberOfScreens,
&mSystemDefaultScale,
@ -64,7 +64,7 @@ nsScreenManagerProxy::GetPrimaryScreen(nsIScreen** outScreen)
if (!mPrimaryScreen) {
ScreenDetails details;
bool success = false;
unused << CallGetPrimaryScreen(&details, &success);
unused << SendGetPrimaryScreen(&details, &success);
if (!success) {
return NS_ERROR_FAILURE;
}
@ -92,7 +92,7 @@ nsScreenManagerProxy::ScreenForRect(int32_t inLeft,
{
bool success = false;
ScreenDetails details;
unused << CallScreenForRect(inLeft, inTop, inWidth, inHeight, &details, &success);
unused << SendScreenForRect(inLeft, inTop, inWidth, inHeight, &details, &success);
if (!success) {
return NS_ERROR_FAILURE;
}
@ -126,7 +126,7 @@ nsScreenManagerProxy::ScreenForNativeWidget(void* aWidget,
// for it.
bool success = false;
ScreenDetails details;
unused << CallScreenForBrowser(tabChild, &details, &success);
unused << SendScreenForBrowser(tabChild, &details, &success);
if (!success) {
return NS_ERROR_FAILURE;
}
@ -177,7 +177,7 @@ nsScreenManagerProxy::EnsureCacheIsValid()
bool success = false;
// Kick off a synchronous IPC call to the parent to get the
// most up-to-date information.
unused << CallRefresh(&mNumberOfScreens, &mSystemDefaultScale, &success);
unused << SendRefresh(&mNumberOfScreens, &mSystemDefaultScale, &success);
if (!success) {
NS_WARNING("Refreshing nsScreenManagerProxy failed in the parent process.");
return false;

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

@ -727,7 +727,7 @@ nsThread::ProcessNextEvent(bool aMayWait, bool* aResult)
// If we're on the main thread, we shouldn't be dispatching CPOWs.
MOZ_RELEASE_ASSERT(mIsMainThread != MAIN_THREAD ||
!ipc::ProcessingUrgentMessages());
!ipc::ParentProcessIsBlocked());
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
return NS_ERROR_NOT_SAME_THREAD;