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