LCOV - code coverage report
Current view: top level - ipc/glue - MessageChannel.h (source / functions) Hit Total Coverage
Test: output.info Lines: 39 82 47.6 %
Date: 2017-07-14 16:53:18 Functions: 19 47 40.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: sw=4 ts=4 et :
       3             :  */
       4             : /* This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       7             : 
       8             : #ifndef ipc_glue_MessageChannel_h
       9             : #define ipc_glue_MessageChannel_h 1
      10             : 
      11             : #include "base/basictypes.h"
      12             : #include "base/message_loop.h"
      13             : 
      14             : #include "nsIMemoryReporter.h"
      15             : #include "mozilla/Atomics.h"
      16             : #include "mozilla/DebugOnly.h"
      17             : #include "mozilla/Monitor.h"
      18             : #include "mozilla/MozPromise.h"
      19             : #include "mozilla/Vector.h"
      20             : #if defined(OS_WIN)
      21             : #include "mozilla/ipc/Neutering.h"
      22             : #endif // defined(OS_WIN)
      23             : #include "mozilla/ipc/Transport.h"
      24             : #if defined(MOZ_CRASHREPORTER) && defined(OS_WIN)
      25             : #include "mozilla/mozalloc_oom.h"
      26             : #include "nsExceptionHandler.h"
      27             : #endif
      28             : #include "MessageLink.h"
      29             : #include "nsThreadUtils.h"
      30             : 
      31             : #include <deque>
      32             : #include <functional>
      33             : #include <map>
      34             : #include <math.h>
      35             : #include <stack>
      36             : #include <vector>
      37             : 
      38             : namespace mozilla {
      39             : namespace ipc {
      40             : 
      41             : class MessageChannel;
      42             : class IToplevelProtocol;
      43             : 
      44             : class RefCountedMonitor : public Monitor
      45             : {
      46             :   public:
      47          33 :     RefCountedMonitor()
      48          33 :         : Monitor("mozilla.ipc.MessageChannel.mMonitor")
      49          33 :     {}
      50             : 
      51          38 :     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMonitor)
      52             : 
      53             :   private:
      54           0 :     ~RefCountedMonitor() {}
      55             : };
      56             : 
      57             : enum class SyncSendError {
      58             :     SendSuccess,
      59             :     PreviousTimeout,
      60             :     SendingCPOWWhileDispatchingSync,
      61             :     SendingCPOWWhileDispatchingUrgent,
      62             :     NotConnectedBeforeSend,
      63             :     DisconnectedDuringSend,
      64             :     CancelledBeforeSend,
      65             :     CancelledAfterSend,
      66             :     TimedOut,
      67             :     ReplyError,
      68             : };
      69             : 
      70             : enum class PromiseRejectReason {
      71             :     SendError,
      72             :     ChannelClosed,
      73             :     HandlerRejected,
      74             :     ActorDestroyed,
      75             :     EndGuard_,
      76             : };
      77             : 
      78             : enum ChannelState {
      79             :     ChannelClosed,
      80             :     ChannelOpening,
      81             :     ChannelConnected,
      82             :     ChannelTimeout,
      83             :     ChannelClosing,
      84             :     ChannelError
      85             : };
      86             : 
      87             : class AutoEnterTransaction;
      88             : 
      89             : class MessageChannel : HasResultCodes, MessageLoop::DestructionObserver
      90             : {
      91             :     friend class ProcessLink;
      92             :     friend class ThreadLink;
      93             : 
      94             :     class CxxStackFrame;
      95             :     class InterruptFrame;
      96             : 
      97             :     typedef mozilla::Monitor Monitor;
      98             : 
      99             :     // We could templatize the actor type but it would unnecessarily
     100             :     // expand the code size. Using the actor address as the
     101             :     // identifier is already good enough.
     102             :     typedef void* ActorIdType;
     103             : 
     104           0 :     struct PromiseHolder
     105             :     {
     106             :         RefPtr<MozPromiseRefcountable> mPromise;
     107             : 
     108             :         // For rejecting and removing the pending promises when a
     109             :         // subprotocol is destoryed.
     110             :         ActorIdType mActorId;
     111             : 
     112             :         std::function<void(MozPromiseRefcountable*,
     113             :                            PromiseRejectReason,
     114             :                            const char*)> mRejectFunction;
     115             :     };
     116             :     static Atomic<size_t> gUnresolvedPromises;
     117             :     friend class PromiseReporter;
     118             : 
     119             :   public:
     120             :     static const int32_t kNoTimeout;
     121             : 
     122             :     typedef IPC::Message Message;
     123             :     typedef IPC::MessageInfo MessageInfo;
     124             :     typedef mozilla::ipc::Transport Transport;
     125             : 
     126             :     explicit MessageChannel(const char *aName,
     127             :                             IToplevelProtocol *aListener);
     128             :     ~MessageChannel();
     129             : 
     130           0 :     IToplevelProtocol *Listener() const {
     131           0 :         return mListener;
     132             :     }
     133             : 
     134             :     // "Open" from the perspective of the transport layer; the underlying
     135             :     // socketpair/pipe should already be created.
     136             :     //
     137             :     // Returns true if the transport layer was successfully connected,
     138             :     // i.e., mChannelState == ChannelConnected.
     139             :     bool Open(Transport* aTransport, MessageLoop* aIOLoop=0, Side aSide=UnknownSide);
     140             : 
     141             :     // "Open" a connection to another thread in the same process.
     142             :     //
     143             :     // Returns true if the transport layer was successfully connected,
     144             :     // i.e., mChannelState == ChannelConnected.
     145             :     //
     146             :     // For more details on the process of opening a channel between
     147             :     // threads, see the extended comment on this function
     148             :     // in MessageChannel.cpp.
     149             :     bool Open(MessageChannel *aTargetChan, MessageLoop *aTargetLoop, Side aSide);
     150             : 
     151             :     // Close the underlying transport channel.
     152             :     void Close();
     153             : 
     154             :     // Force the channel to behave as if a channel error occurred. Valid
     155             :     // for process links only, not thread links.
     156             :     void CloseWithError();
     157             : 
     158             :     void CloseWithTimeout();
     159             : 
     160           2 :     void SetAbortOnError(bool abort)
     161             :     {
     162           2 :         mAbortOnError = abort;
     163           2 :     }
     164             : 
     165             :     // Call aInvoke for each pending message until it returns false.
     166             :     // XXX: You must get permission from an IPC peer to use this function
     167             :     //      since it requires custom deserialization and re-orders events.
     168             :     void PeekMessages(const std::function<bool(const Message& aMsg)>& aInvoke);
     169             : 
     170             :     // Misc. behavioral traits consumers can request for this channel
     171             :     enum ChannelFlags {
     172             :       REQUIRE_DEFAULT                         = 0,
     173             :       // Windows: if this channel operates on the UI thread, indicates
     174             :       // WindowsMessageLoop code should enable deferred native message
     175             :       // handling to prevent deadlocks. Should only be used for protocols
     176             :       // that manage child processes which might create native UI, like
     177             :       // plugins.
     178             :       REQUIRE_DEFERRED_MESSAGE_PROTECTION     = 1 << 0,
     179             :       // Windows: When this flag is specified, any wait that occurs during
     180             :       // synchronous IPC will be alertable, thus allowing a11y code in the
     181             :       // chrome process to reenter content while content is waiting on a
     182             :       // synchronous call.
     183             :       REQUIRE_A11Y_REENTRY                    = 1 << 1,
     184             :     };
     185           0 :     void SetChannelFlags(ChannelFlags aFlags) { mFlags = aFlags; }
     186             :     ChannelFlags GetChannelFlags() { return mFlags; }
     187             : 
     188             :     // Asynchronously send a message to the other side of the channel
     189             :     bool Send(Message* aMsg);
     190             : 
     191             :     // Asynchronously send a message to the other side of the channel
     192             :     // and wait for asynchronous reply
     193             :     template<typename Promise>
     194           0 :     bool Send(Message* aMsg, Promise* aPromise, ActorIdType aActorId) {
     195           0 :         int32_t seqno = NextSeqno();
     196           0 :         aMsg->set_seqno(seqno);
     197           0 :         if (!Send(aMsg)) {
     198           0 :             return false;
     199             :         }
     200           0 :         PromiseHolder holder;
     201           0 :         holder.mPromise = aPromise;
     202           0 :         holder.mActorId = aActorId;
     203           0 :         holder.mRejectFunction = [](MozPromiseRefcountable* aRejectPromise,
     204             :                                     PromiseRejectReason aReason,
     205           0 :                                     const char* aRejectSite) {
     206           0 :             static_cast<Promise*>(aRejectPromise)->Reject(aReason, aRejectSite);
     207           0 :         };
     208           0 :         mPendingPromises.insert(std::make_pair(seqno, Move(holder)));
     209           0 :         gUnresolvedPromises++;
     210           0 :         return true;
     211             :     }
     212             : 
     213             :     void SendBuildID();
     214             : 
     215             :     // Asynchronously deliver a message back to this side of the
     216             :     // channel
     217             :     bool Echo(Message* aMsg);
     218             : 
     219             :     // Synchronously send |msg| (i.e., wait for |reply|)
     220             :     bool Send(Message* aMsg, Message* aReply);
     221             : 
     222             :     // Make an Interrupt call to the other side of the channel
     223             :     bool Call(Message* aMsg, Message* aReply);
     224             : 
     225             :     // Wait until a message is received
     226             :     bool WaitForIncomingMessage();
     227             : 
     228             :     bool CanSend() const;
     229             : 
     230             :     // Remove and return a promise that needs reply
     231             :     already_AddRefed<MozPromiseRefcountable> PopPromise(const Message& aMsg);
     232             : 
     233             :     // Used to reject and remove pending promises owned by the given
     234             :     // actor when it's about to be destroyed.
     235             :     void RejectPendingPromisesForActor(ActorIdType aActorId);
     236             : 
     237             :     // If sending a sync message returns an error, this function gives a more
     238             :     // descriptive error message.
     239             :     SyncSendError LastSendError() const {
     240             :         AssertWorkerThread();
     241             :         return mLastSendError;
     242             :     }
     243             : 
     244             :     // Currently only for debugging purposes, doesn't aquire mMonitor.
     245             :     ChannelState GetChannelState__TotallyRacy() const {
     246             :         return mChannelState;
     247             :     }
     248             : 
     249             :     void SetReplyTimeoutMs(int32_t aTimeoutMs);
     250             : 
     251         455 :     bool IsOnCxxStack() const {
     252         455 :         return !mCxxStackFrames.empty();
     253             :     }
     254             : 
     255             :     bool IsInTransaction() const;
     256             :     void CancelCurrentTransaction();
     257             : 
     258             :     // Force all calls to Send to defer actually sending messages. This will
     259             :     // cause sync messages to block until another thread calls
     260             :     // StopPostponingSends.
     261             :     //
     262             :     // This must be called from the worker thread.
     263             :     void BeginPostponingSends();
     264             : 
     265             :     // Stop postponing sent messages, and immediately flush all postponed
     266             :     // messages to the link. This may be called from any thread.
     267             :     //
     268             :     // Note that there are no ordering guarantees between two different
     269             :     // MessageChannels. If channel B sends a message, then stops postponing
     270             :     // channel A, messages from A may arrive before B. The easiest way to order
     271             :     // this, if needed, is to make B send a sync message.
     272             :     void StopPostponingSends();
     273             : 
     274             :     /**
     275             :      * This function is used by hang annotation code to determine which IPDL
     276             :      * actor is highest in the call stack at the time of the hang. It should
     277             :      * be called from the main thread when a sync or intr message is about to
     278             :      * be sent.
     279             :      */
     280             :     int32_t GetTopmostMessageRoutingId() const;
     281             : 
     282             :     // Unsound_IsClosed and Unsound_NumQueuedMessages are safe to call from any
     283             :     // thread, but they make no guarantees about whether you'll get an
     284             :     // up-to-date value; the values are written on one thread and read without
     285             :     // locking, on potentially different threads.  Thus you should only use
     286             :     // them when you don't particularly care about getting a recent value (e.g.
     287             :     // in a memory report).
     288           0 :     bool Unsound_IsClosed() const {
     289           0 :         return mLink ? mLink->Unsound_IsClosed() : true;
     290             :     }
     291           0 :     uint32_t Unsound_NumQueuedMessages() const {
     292           0 :         return mLink ? mLink->Unsound_NumQueuedMessages() : 0;
     293             :     }
     294             : 
     295             :     static bool IsPumpingMessages() {
     296             :         return sIsPumpingMessages;
     297             :     }
     298             :     static void SetIsPumpingMessages(bool aIsPumping) {
     299             :         sIsPumpingMessages = aIsPumping;
     300             :     }
     301             : 
     302             : #ifdef OS_WIN
     303             :     struct MOZ_STACK_CLASS SyncStackFrame
     304             :     {
     305             :         SyncStackFrame(MessageChannel* channel, bool interrupt);
     306             :         ~SyncStackFrame();
     307             : 
     308             :         bool mInterrupt;
     309             :         bool mSpinNestedEvents;
     310             :         bool mListenerNotified;
     311             :         MessageChannel* mChannel;
     312             : 
     313             :         // The previous stack frame for this channel.
     314             :         SyncStackFrame* mPrev;
     315             : 
     316             :         // The previous stack frame on any channel.
     317             :         SyncStackFrame* mStaticPrev;
     318             :     };
     319             :     friend struct MessageChannel::SyncStackFrame;
     320             : 
     321             :     static bool IsSpinLoopActive() {
     322             :         for (SyncStackFrame* frame = sStaticTopFrame; frame; frame = frame->mPrev) {
     323             :             if (frame->mSpinNestedEvents)
     324             :                 return true;
     325             :         }
     326             :         return false;
     327             :     }
     328             : 
     329             :   protected:
     330             :     // The deepest sync stack frame for this channel.
     331             :     SyncStackFrame* mTopFrame;
     332             : 
     333             :     bool mIsSyncWaitingOnNonMainThread;
     334             : 
     335             :     // The deepest sync stack frame on any channel.
     336             :     static SyncStackFrame* sStaticTopFrame;
     337             : 
     338             :   public:
     339             :     void ProcessNativeEventsInInterruptCall();
     340             :     static void NotifyGeckoEventDispatch();
     341             : 
     342             :   private:
     343             :     void SpinInternalEventLoop();
     344             : #if defined(ACCESSIBILITY)
     345             :     bool WaitForSyncNotifyWithA11yReentry();
     346             : #endif // defined(ACCESSIBILITY)
     347             : #endif // defined(OS_WIN)
     348             : 
     349             :   private:
     350             :     void CommonThreadOpenInit(MessageChannel *aTargetChan, Side aSide);
     351             :     void OnOpenAsSlave(MessageChannel *aTargetChan, Side aSide);
     352             : 
     353             :     void PostErrorNotifyTask();
     354             :     void OnNotifyMaybeChannelError();
     355             :     void ReportConnectionError(const char* aChannelName, Message* aMsg = nullptr) const;
     356             :     void ReportMessageRouteError(const char* channelName) const;
     357             :     bool MaybeHandleError(Result code, const Message& aMsg, const char* channelName);
     358             : 
     359             :     void Clear();
     360             : 
     361             :     // Send OnChannelConnected notification to listeners.
     362             :     void DispatchOnChannelConnected();
     363             : 
     364             :     bool InterruptEventOccurred();
     365             :     bool HasPendingEvents();
     366             : 
     367             :     void ProcessPendingRequests(AutoEnterTransaction& aTransaction);
     368             :     bool ProcessPendingRequest(Message &&aUrgent);
     369             : 
     370             :     void MaybeUndeferIncall();
     371             :     void EnqueuePendingMessages();
     372             : 
     373             :     // Dispatches an incoming message to its appropriate handler.
     374             :     void DispatchMessage(Message &&aMsg);
     375             : 
     376             :     // DispatchMessage will route to one of these functions depending on the
     377             :     // protocol type of the message.
     378             :     void DispatchSyncMessage(const Message &aMsg, Message*& aReply);
     379             :     void DispatchUrgentMessage(const Message &aMsg);
     380             :     void DispatchAsyncMessage(const Message &aMsg);
     381             :     void DispatchRPCMessage(const Message &aMsg);
     382             :     void DispatchInterruptMessage(Message &&aMsg, size_t aStackDepth);
     383             : 
     384             :     // Return true if the wait ended because a notification was received.
     385             :     //
     386             :     // Return false if the time elapsed from when we started the process of
     387             :     // waiting until afterwards exceeded the currently allotted timeout.
     388             :     // That *DOES NOT* mean false => "no event" (== timeout); there are many
     389             :     // circumstances that could cause the measured elapsed time to exceed the
     390             :     // timeout EVEN WHEN we were notified.
     391             :     //
     392             :     // So in sum: true is a meaningful return value; false isn't,
     393             :     // necessarily.
     394             :     bool WaitForSyncNotify(bool aHandleWindowsMessages);
     395             :     bool WaitForInterruptNotify();
     396             : 
     397             :     bool WaitResponse(bool aWaitTimedOut);
     398             : 
     399             :     bool ShouldContinueFromTimeout();
     400             : 
     401             :     void EndTimeout();
     402             :     void CancelTransaction(int transaction);
     403             : 
     404             :     void RepostAllMessages();
     405             : 
     406             :     // The "remote view of stack depth" can be different than the
     407             :     // actual stack depth when there are out-of-turn replies.  When we
     408             :     // receive one, our actual Interrupt stack depth doesn't decrease, but
     409             :     // the other side (that sent the reply) thinks it has.  So, the
     410             :     // "view" returned here is |stackDepth| minus the number of
     411             :     // out-of-turn replies.
     412             :     //
     413             :     // Only called from the worker thread.
     414           0 :     size_t RemoteViewOfStackDepth(size_t stackDepth) const {
     415           0 :         AssertWorkerThread();
     416           0 :         return stackDepth - mOutOfTurnReplies.size();
     417             :     }
     418             : 
     419           3 :     int32_t NextSeqno() {
     420           3 :         AssertWorkerThread();
     421           3 :         return (mSide == ChildSide) ? --mNextSeqno : ++mNextSeqno;
     422             :     }
     423             : 
     424             :     // This helper class manages mCxxStackDepth on behalf of MessageChannel.
     425             :     // When the stack depth is incremented from zero to non-zero, it invokes
     426             :     // a callback, and similarly for when the depth goes from non-zero to zero.
     427             :     void EnteredCxxStack();
     428             :     void ExitedCxxStack();
     429             : 
     430             :     void EnteredCall();
     431             :     void ExitedCall();
     432             : 
     433             :     void EnteredSyncSend();
     434             :     void ExitedSyncSend();
     435             : 
     436             :     void DebugAbort(const char* file, int line, const char* cond,
     437             :                     const char* why,
     438             :                     bool reply=false);
     439             : 
     440             :     // This method is only safe to call on the worker thread, or in a
     441             :     // debugger with all threads paused.
     442             :     void DumpInterruptStack(const char* const pfx="") const;
     443             : 
     444             :   private:
     445             :     // Called from both threads
     446           0 :     size_t InterruptStackDepth() const {
     447           0 :         mMonitor->AssertCurrentThreadOwns();
     448           0 :         return mInterruptStack.size();
     449             :     }
     450             : 
     451         526 :     bool AwaitingInterruptReply() const {
     452         526 :         mMonitor->AssertCurrentThreadOwns();
     453         526 :         return !mInterruptStack.empty();
     454             :     }
     455         526 :     bool AwaitingIncomingMessage() const {
     456         526 :         mMonitor->AssertCurrentThreadOwns();
     457         526 :         return mIsWaitingForIncoming;
     458             :     }
     459             : 
     460             :     class MOZ_STACK_CLASS AutoEnterWaitForIncoming
     461             :     {
     462             :     public:
     463           0 :         explicit AutoEnterWaitForIncoming(MessageChannel& aChannel)
     464           0 :             : mChannel(aChannel)
     465             :         {
     466           0 :             aChannel.mMonitor->AssertCurrentThreadOwns();
     467           0 :             aChannel.mIsWaitingForIncoming = true;
     468           0 :         }
     469             : 
     470           0 :         ~AutoEnterWaitForIncoming()
     471           0 :         {
     472           0 :             mChannel.mIsWaitingForIncoming = false;
     473           0 :         }
     474             : 
     475             :     private:
     476             :         MessageChannel& mChannel;
     477             :     };
     478             :     friend class AutoEnterWaitForIncoming;
     479             : 
     480             :     // Returns true if we're dispatching an async message's callback.
     481           0 :     bool DispatchingAsyncMessage() const {
     482           0 :         AssertWorkerThread();
     483           0 :         return mDispatchingAsyncMessage;
     484             :     }
     485             : 
     486           6 :     int DispatchingAsyncMessageNestedLevel() const {
     487           6 :         AssertWorkerThread();
     488           6 :         return mDispatchingAsyncMessageNestedLevel;
     489             :     }
     490             : 
     491             :     bool Connected() const;
     492             : 
     493             :   private:
     494             :     // Executed on the IO thread.
     495             :     void NotifyWorkerThread();
     496             : 
     497             :     // Return true if |aMsg| is a special message targeted at the IO
     498             :     // thread, in which case it shouldn't be delivered to the worker.
     499             :     bool MaybeInterceptSpecialIOMessage(const Message& aMsg);
     500             : 
     501             :     void OnChannelConnected(int32_t peer_id);
     502             : 
     503             :     // Tell the IO thread to close the channel and wait for it to ACK.
     504             :     void SynchronouslyClose();
     505             : 
     506             :     // Returns true if ShouldDeferMessage(aMsg) is guaranteed to return true.
     507             :     // Otherwise, the result of ShouldDeferMessage(aMsg) may be true or false,
     508             :     // depending on context.
     509             :     static bool IsAlwaysDeferred(const Message& aMsg);
     510             : 
     511             :     // Helper for sending a message via the link. This should only be used for
     512             :     // non-special messages that might have to be postponed.
     513             :     void SendMessageToLink(Message* aMsg);
     514             : 
     515             :     bool WasTransactionCanceled(int transaction);
     516             :     bool ShouldDeferMessage(const Message& aMsg);
     517             :     bool ShouldDeferInterruptMessage(const Message& aMsg, size_t aStackDepth);
     518             :     void OnMessageReceivedFromLink(Message&& aMsg);
     519             :     void OnChannelErrorFromLink();
     520             : 
     521             :   private:
     522             :     // Run on the not current thread.
     523             :     void NotifyChannelClosed();
     524             :     void NotifyMaybeChannelError();
     525             : 
     526             :   private:
     527             :     // Can be run on either thread
     528        4848 :     void AssertWorkerThread() const
     529             :     {
     530        4848 :         MOZ_ASSERT(mWorkerThread, "Channel hasn't been opened yet");
     531        4848 :         MOZ_RELEASE_ASSERT(mWorkerThread == GetCurrentVirtualThread(),
     532             :                            "not on worker thread!");
     533        4848 :     }
     534             : 
     535             :     // The "link" thread is either the I/O thread (ProcessLink) or the
     536             :     // other actor's work thread (ThreadLink).  In either case, it is
     537             :     // NOT our worker thread.
     538        1062 :     void AssertLinkThread() const
     539             :     {
     540        1062 :         MOZ_ASSERT(mWorkerThread, "Channel hasn't been opened yet");
     541        1062 :         MOZ_RELEASE_ASSERT(mWorkerThread != GetCurrentVirtualThread(),
     542             :                            "on worker thread but should not be!");
     543        1062 :     }
     544             : 
     545             :   private:
     546             :     class MessageTask :
     547             :         public CancelableRunnable,
     548             :         public LinkedListElement<RefPtr<MessageTask>>,
     549             :         public nsIRunnablePriority
     550             :     {
     551             :     public:
     552             :         explicit MessageTask(MessageChannel* aChannel, Message&& aMessage);
     553             : 
     554             :         NS_DECL_ISUPPORTS_INHERITED
     555             : 
     556             :         NS_IMETHOD Run() override;
     557             :         nsresult Cancel() override;
     558             :         NS_IMETHOD GetPriority(uint32_t* aPriority) override;
     559             :         void Post();
     560             :         void Clear();
     561             : 
     562           0 :         bool IsScheduled() const { return mScheduled; }
     563             : 
     564         814 :         Message& Msg() { return mMessage; }
     565             :         const Message& Msg() const { return mMessage; }
     566             : 
     567             :     private:
     568             :         MessageTask() = delete;
     569             :         MessageTask(const MessageTask&) = delete;
     570        1359 :         ~MessageTask() {}
     571             : 
     572             :         MessageChannel* mChannel;
     573             :         Message mMessage;
     574             :         bool mScheduled : 1;
     575             :     };
     576             : 
     577             :     bool ShouldRunMessage(const Message& aMsg);
     578             :     void RunMessage(MessageTask& aTask);
     579             : 
     580             :     typedef LinkedList<RefPtr<MessageTask>> MessageQueue;
     581             :     typedef std::map<size_t, Message> MessageMap;
     582             :     typedef std::map<size_t, PromiseHolder> PromiseMap;
     583             :     typedef IPC::Message::msgid_t msgid_t;
     584             : 
     585             :     void WillDestroyCurrentMessageLoop() override;
     586             : 
     587             :   private:
     588             :     // This will be a string literal, so lifetime is not an issue.
     589             :     const char* mName;
     590             : 
     591             :     // Based on presumption the listener owns and overlives the channel,
     592             :     // this is never nullified.
     593             :     IToplevelProtocol* mListener;
     594             :     ChannelState mChannelState;
     595             :     RefPtr<RefCountedMonitor> mMonitor;
     596             :     Side mSide;
     597             :     MessageLink* mLink;
     598             :     MessageLoop* mWorkerLoop;           // thread where work is done
     599             :     RefPtr<CancelableRunnable> mChannelErrorTask;  // NotifyMaybeChannelError runnable
     600             : 
     601             :     // Thread we are allowed to send and receive on. This persists even after
     602             :     // mWorkerLoop is cleared during channel shutdown.
     603             :     PRThread* mWorkerThread;
     604             : 
     605             :     // Timeout periods are broken up in two to prevent system suspension from
     606             :     // triggering an abort. This method (called by WaitForEvent with a 'did
     607             :     // timeout' flag) decides if we should wait again for half of mTimeoutMs
     608             :     // or give up.
     609             :     int32_t mTimeoutMs;
     610             :     bool mInTimeoutSecondHalf;
     611             : 
     612             :     // Worker-thread only; sequence numbers for messages that require
     613             :     // replies.
     614             :     int32_t mNextSeqno;
     615             : 
     616             :     static bool sIsPumpingMessages;
     617             : 
     618             :     // If ::Send returns false, this gives a more descriptive error.
     619             :     SyncSendError mLastSendError;
     620             : 
     621             :     template<class T>
     622             :     class AutoSetValue {
     623             :       public:
     624         907 :         explicit AutoSetValue(T &var, const T &newValue)
     625         907 :           : mVar(var), mPrev(var), mNew(newValue)
     626             :         {
     627         907 :             mVar = newValue;
     628         907 :         }
     629         901 :         ~AutoSetValue() {
     630             :             // The value may have been zeroed if the transaction was
     631             :             // canceled. In that case we shouldn't return it to its previous
     632             :             // value.
     633         901 :             if (mVar == mNew) {
     634         901 :                 mVar = mPrev;
     635             :             }
     636         901 :         }
     637             :       private:
     638             :         T& mVar;
     639             :         T mPrev;
     640             :         T mNew;
     641             :     };
     642             : 
     643             :     bool mDispatchingAsyncMessage;
     644             :     int mDispatchingAsyncMessageNestedLevel;
     645             : 
     646             :     // When we send an urgent request from the parent process, we could race
     647             :     // with an RPC message that was issued by the child beforehand. In this
     648             :     // case, if the parent were to wake up while waiting for the urgent reply,
     649             :     // and process the RPC, it could send an additional urgent message. The
     650             :     // child would wake up to process the urgent message (as it always will),
     651             :     // then send a reply, which could be received by the parent out-of-order
     652             :     // with respect to the first urgent reply.
     653             :     //
     654             :     // To address this problem, urgent or RPC requests are associated with a
     655             :     // "transaction". Whenever one side of the channel wishes to start a
     656             :     // chain of RPC/urgent messages, it allocates a new transaction ID. Any
     657             :     // messages the parent receives, not apart of this transaction, are
     658             :     // deferred. When issuing RPC/urgent requests on top of a started
     659             :     // transaction, the initiating transaction ID is used.
     660             :     //
     661             :     // To ensure IDs are unique, we use sequence numbers for transaction IDs,
     662             :     // which grow in opposite directions from child to parent.
     663             : 
     664             :     friend class AutoEnterTransaction;
     665             :     AutoEnterTransaction *mTransactionStack;
     666             : 
     667             :     int32_t CurrentNestedInsideSyncTransaction() const;
     668             : 
     669             :     bool AwaitingSyncReply() const;
     670             :     int AwaitingSyncReplyNestedLevel() const;
     671             : 
     672             :     bool DispatchingSyncMessage() const;
     673             :     int DispatchingSyncMessageNestedLevel() const;
     674             : 
     675             : #ifdef DEBUG
     676             :     void AssertMaybeDeferredCountCorrect();
     677             : #else
     678             :     void AssertMaybeDeferredCountCorrect() {}
     679             : #endif
     680             : 
     681             :     // If a sync message times out, we store its sequence number here. Any
     682             :     // future sync messages will fail immediately. Once the reply for original
     683             :     // sync message is received, we allow sync messages again.
     684             :     //
     685             :     // When a message times out, nothing is done to inform the other side. The
     686             :     // other side will eventually dispatch the message and send a reply. Our
     687             :     // side is responsible for replying to all sync messages sent by the other
     688             :     // side when it dispatches the timed out message. The response is always an
     689             :     // error.
     690             :     //
     691             :     // A message is only timed out if it initiated a transaction. This avoids
     692             :     // hitting a lot of corner cases with message nesting that we don't really
     693             :     // care about.
     694             :     int32_t mTimedOutMessageSeqno;
     695             :     int mTimedOutMessageNestedLevel;
     696             : 
     697             :     // Queue of all incoming messages.
     698             :     //
     699             :     // If both this side and the other side are functioning correctly, the queue
     700             :     // can only be in certain configurations.  Let
     701             :     //
     702             :     //   |A<| be an async in-message,
     703             :     //   |S<| be a sync in-message,
     704             :     //   |C<| be an Interrupt in-call,
     705             :     //   |R<| be an Interrupt reply.
     706             :     //
     707             :     // The queue can only match this configuration
     708             :     //
     709             :     //  A<* (S< | C< | R< (?{mInterruptStack.size() == 1} A<* (S< | C<)))
     710             :     //
     711             :     // The other side can send as many async messages |A<*| as it wants before
     712             :     // sending us a blocking message.
     713             :     //
     714             :     // The first case is |S<|, a sync in-msg.  The other side must be blocked,
     715             :     // and thus can't send us any more messages until we process the sync
     716             :     // in-msg.
     717             :     //
     718             :     // The second case is |C<|, an Interrupt in-call; the other side must be blocked.
     719             :     // (There's a subtlety here: this in-call might have raced with an
     720             :     // out-call, but we detect that with the mechanism below,
     721             :     // |mRemoteStackDepth|, and races don't matter to the queue.)
     722             :     //
     723             :     // Final case, the other side replied to our most recent out-call |R<|.
     724             :     // If that was the *only* out-call on our stack, |?{mInterruptStack.size() == 1}|,
     725             :     // then other side "finished with us," and went back to its own business.
     726             :     // That business might have included sending any number of async message
     727             :     // |A<*| until sending a blocking message |(S< | C<)|.  If we had more than
     728             :     // one Interrupt call on our stack, the other side *better* not have sent us
     729             :     // another blocking message, because it's blocked on a reply from us.
     730             :     //
     731             :     MessageQueue mPending;
     732             : 
     733             :     // The number of messages in mPending for which IsAlwaysDeferred is false
     734             :     // (i.e., the number of messages that might not be deferred, depending on
     735             :     // context).
     736             :     size_t mMaybeDeferredPendingCount;
     737             : 
     738             :     // Stack of all the out-calls on which this channel is awaiting responses.
     739             :     // Each stack refers to a different protocol and the stacks are mutually
     740             :     // exclusive: multiple outcalls of the same kind cannot be initiated while
     741             :     // another is active.
     742             :     std::stack<MessageInfo> mInterruptStack;
     743             : 
     744             :     // This is what we think the Interrupt stack depth is on the "other side" of this
     745             :     // Interrupt channel.  We maintain this variable so that we can detect racy Interrupt
     746             :     // calls.  With each Interrupt out-call sent, we send along what *we* think the
     747             :     // stack depth of the remote side is *before* it will receive the Interrupt call.
     748             :     //
     749             :     // After sending the out-call, our stack depth is "incremented" by pushing
     750             :     // that pending message onto mPending.
     751             :     //
     752             :     // Then when processing an in-call |c|, it must be true that
     753             :     //
     754             :     //   mInterruptStack.size() == c.remoteDepth
     755             :     //
     756             :     // I.e., my depth is actually the same as what the other side thought it
     757             :     // was when it sent in-call |c|.  If this fails to hold, we have detected
     758             :     // racy Interrupt calls.
     759             :     //
     760             :     // We then increment mRemoteStackDepth *just before* processing the
     761             :     // in-call, since we know the other side is waiting on it, and decrement
     762             :     // it *just after* finishing processing that in-call, since our response
     763             :     // will pop the top of the other side's |mPending|.
     764             :     //
     765             :     // One nice aspect of this race detection is that it is symmetric; if one
     766             :     // side detects a race, then the other side must also detect the same race.
     767             :     size_t mRemoteStackDepthGuess;
     768             : 
     769             :     // Approximation of code frames on the C++ stack. It can only be
     770             :     // interpreted as the implication:
     771             :     //
     772             :     //  !mCxxStackFrames.empty() => MessageChannel code on C++ stack
     773             :     //
     774             :     // This member is only accessed on the worker thread, and so is not
     775             :     // protected by mMonitor.  It is managed exclusively by the helper
     776             :     // |class CxxStackFrame|.
     777             :     mozilla::Vector<InterruptFrame> mCxxStackFrames;
     778             : 
     779             :     // Did we process an Interrupt out-call during this stack?  Only meaningful in
     780             :     // ExitedCxxStack(), from which this variable is reset.
     781             :     bool mSawInterruptOutMsg;
     782             : 
     783             :     // Are we waiting on this channel for an incoming message? This is used
     784             :     // to implement WaitForIncomingMessage(). Must only be accessed while owning
     785             :     // mMonitor.
     786             :     bool mIsWaitingForIncoming;
     787             : 
     788             :     // Map of replies received "out of turn", because of Interrupt
     789             :     // in-calls racing with replies to outstanding in-calls.  See
     790             :     // https://bugzilla.mozilla.org/show_bug.cgi?id=521929.
     791             :     MessageMap mOutOfTurnReplies;
     792             : 
     793             :     // Map of async Promises that are still waiting replies.
     794             :     PromiseMap mPendingPromises;
     795             : 
     796             :     // Stack of Interrupt in-calls that were deferred because of race
     797             :     // conditions.
     798             :     std::stack<Message> mDeferred;
     799             : 
     800             : #ifdef OS_WIN
     801             :     HANDLE mEvent;
     802             : #endif
     803             : 
     804             :     // Should the channel abort the process from the I/O thread when
     805             :     // a channel error occurs?
     806             :     bool mAbortOnError;
     807             : 
     808             :     // True if the listener has already been notified of a channel close or
     809             :     // error.
     810             :     bool mNotifiedChannelDone;
     811             : 
     812             :     // See SetChannelFlags
     813             :     ChannelFlags mFlags;
     814             : 
     815             :     // Task and state used to asynchronously notify channel has been connected
     816             :     // safely.  This is necessary to be able to cancel notification if we are
     817             :     // closed at the same time.
     818             :     RefPtr<CancelableRunnable> mOnChannelConnectedTask;
     819             :     bool mPeerPidSet;
     820             :     int32_t mPeerPid;
     821             : 
     822             :     // Channels can enter messages are not sent immediately; instead, they are
     823             :     // held in a queue until another thread deems it is safe to send them.
     824             :     bool mIsPostponingSends;
     825             :     std::vector<UniquePtr<Message>> mPostponedSends;
     826             : };
     827             : 
     828             : void
     829             : CancelCPOWs();
     830             : 
     831             : } // namespace ipc
     832             : } // namespace mozilla
     833             : 
     834             : namespace IPC {
     835             : template <>
     836             : struct ParamTraits<mozilla::ipc::PromiseRejectReason>
     837             :     : public ContiguousEnumSerializer<mozilla::ipc::PromiseRejectReason,
     838             :                                       mozilla::ipc::PromiseRejectReason::SendError,
     839             :                                       mozilla::ipc::PromiseRejectReason::EndGuard_>
     840             : { };
     841             : } // namespace IPC
     842             : 
     843             : #endif  // ifndef ipc_glue_MessageChannel_h

Generated by: LCOV version 1.13