1IPDL: Inter-Thread and Inter-Process Message Passing
2====================================================
3
4The Idea
5--------
6
7**IPDL**, the "Inter-[thread|process] Protocol Definition Language", is the
8Mozilla-specific language that allows code to communicate between system
9threads or processes in a standardized, efficient, safe, secure and
10platform-agnostic way.  IPDL communications take place between *parent* and
11*child* objects called *actors*.  The architecture is inspired by the `actor
12model <https://en.wikipedia.org/wiki/Actor_model>`_.
13
14.. note::
15    IPDL actors differ from the actor model in one significant way -- all
16    IPDL communications are *only* between a parent and its only child.
17
18The actors that constitute a parent/child pair are called **peers**.  Peer
19actors communicate through an **endpoint**, which is an end of a message pipe.
20An actor is explicitly bound to its endpoint, which in turn is bound to a
21particular thread soon after it is constructed.  An actor never changes its
22endpoint and may only send and receive predeclared **messages** from/to that
23endpoint, on that thread.  Violations result in runtime errors.  A thread may
24be bound to many otherwise unrelated actors but an endpoint supports
25**top-level** actors and any actors they **manage** (see below).
26
27.. note::
28     More precisely, endpoints can be bound to any ``nsISerialEventTarget``,
29     which are themselves associated with a specific thread.  By default,
30     IPDL will bind to the current thread's "main" serial event target,
31     which, if it exists, is retrieved with ``GetCurrentSerialEventTarget``.
32     For the sake of clarity, this document will frequently refer to actors
33     as bound to threads, although the more precise interpretation of serial
34     event targets is also always valid.
35
36.. note::
37    Internally, we use the "Ports" component of the `Chromium Mojo`_ library
38    to *multiplex* multiple endpoints (and, therefore, multiple top-level
39    actors).  This means that the endpoints communicate over the same native
40    pipe, which conserves limited OS resources.  The implications of this are
41    discussed in `IPDL Best Practices`_.
42
43Parent and child actors may be bound to threads in different processes, in
44different threads in the same process, or even in the same thread in the same
45process.  That last option may seem unreasonable but actors are versatile and
46their layout can be established at run-time so this could theoretically arise
47as the result of run-time choices.  One large example of this versatility is
48``PCompositorBridge`` actors, which in different cases connect endpoints in the
49main process and the GPU process (for UI rendering on Windows), in a content
50process and the GPU process (for content rendering on Windows), in the main
51process and the content process (for content rendering on Mac, where there is
52no GPU process), or between threads on the main process (UI rendering on Mac).
53For the most part, this does not require elaborate or redundant coding; it
54just needs endpoints to be bound judiciously at runtime.  The example in
55:ref:`Connecting With Other Processes` shows one way this can be done.  It
56also shows that, without proper plain-language documentation of *all* of the
57ways endpoints are configured, this can quickly lead to unmaintainable code.
58Be sure to document your endpoint bindings throroughly!!!
59
60.. _Chromium Mojo: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/mojo/core/README.md#Port
61
62The Approach
63------------
64
65The actor framework will schedule tasks to run on its associated event target,
66in response to messages it receives.  Messages are specified in an IPDL
67**protocol** file and the response handler tasks are defined per-message by C++
68methods.  As actors only communicate in pairs, and each is bound to one thread,
69sending is always done sequentially, never concurrently (same for receiving).
70This means that it can, and does, guarantee that an actor will always receive
71messages in the same order they were sent by its related actor -- and that this
72order is well defined since the related actor can only send from one thread.
73
74.. warning::
75    There are a few (rare) exceptions to the message order guarantee.  They
76    include  `synchronous nested`_  messages, `interrupt`_ messages, and
77    messages with a ``[Priority]`` or ``[Compress]`` annotation.
78
79An IPDL protocol file specifies the messages that may be sent between parent
80and child actors, as well as the direction and payload of those messages.
81Messages look like function calls but, from the standpoint of their caller,
82they may start and end at any time in the future -- they are *asynchronous*,
83so they won't block their sending actors or any other components that may be
84running in the actor's thread's ``MessageLoop``.
85
86.. note::
87    Not all IPDL messages are asynchronous.  Again, we run into exceptions for
88    messages that are synchronous, `synchronous nested`_ or `interrupt`_.  Use
89    of synchronous and nested messages is strongly discouraged but may not
90    always be avoidable.  They will be defined later, along with superior
91    alternatives to both that should work in nearly all cases.  Interrupt
92    messages were prone to misuse and are deprecated, with removal expected in
93    the near future
94    (`Bug 1729044 <https://bugzilla.mozilla.org/show_bug.cgi?id=1729044>`_).
95
96Protocol files are compiled by the *IPDL compiler* in an early stage of the
97build process.  The compiler generates C++ code that reflects the protocol.
98Specifically, it creates one C++ class that represents the parent actor and one
99that represents the child.  The generated files are then automatically included
100in the C++ build process.  The generated classes contain public methods for
101sending the protocol messages, which client code will use as the entry-point to
102IPC communication.  The generated methods are built atop our IPC framework,
103defined in `/ipc <https://searchfox.org/mozilla-central/source/ipc>`_, that
104standardizes the safe and secure use of sockets, pipes, shared memory, etc on
105all supported platforms.  See `Using The IPDL compiler`_ for more on
106integration with the build process.
107
108Client code must be written that subclasses these generated classes, in order
109to add handlers for the tasks generated to respond to each message.  It must
110also add routines (``ParamTraits``) that define serialization and
111deserialization for any types used in the payload of a message that aren't
112already known to the IPDL system.  Primitive types, and a bunch of Mozilla
113types, have predefined ``ParamTraits`` (`here
114<https://searchfox.org/mozilla-central/source/ipc/glue/IPCMessageUtils.h>`__
115and `here
116<https://searchfox.org/mozilla-central/source/ipc/glue/IPCMessageUtilsSpecializations.h>`__).
117
118.. note::
119    Among other things, client code that uses the generated code must include
120    ``chromium-config.mozbuild`` in its ``moz.build`` file.  See `Using The
121    IPDL compiler`_ for a complete list of required build changes.
122
123.. _interrupt: `The Old Ways`_
124.. _synchronous nested: `The Rest`_
125
126The Steps To Making A New Actor
127~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128
129#. Decide what folder you will work in and create:
130
131    #. An IPDL protocol file, named for your actor (e.g. ``PMyActor.ipdl`` --
132       actor protocols must begin with a ``P``).  See `The Protocol Language`_.
133    #. Properly-named source files for your actor's parent and child
134       implementations (e.g. ``MyActorParent.h``, ``MyActorChild.h`` and,
135       optionally, adjacent .cpp files).  See `The C++ Interface`_.
136    #. IPDL-specific updates to the ``moz.build`` file.  See `Using The IPDL
137       compiler`_.
138#. Write your actor protocol (.ipdl) file:
139
140    #. Decide whether you need a top-level actor or a managed actor.  See
141       `Top Level Actors`_.
142    #. Find/write the IPDL and C++ data types you will use in communication.
143       Write ``ParamTraits`` for C++ data types that don't have them.  See
144       `Generating IPDL-Aware C++ Data Types: IPDL Structs and Unions`_ for IPDL
145       structures.  See `Referencing Externally Defined Data Types: IPDL
146       Includes`_ and `ParamTraits`_ for C++ data types.
147    #. Write your actor and its messages.  See `Defining Actors`_.
148#. Write C++ code to create and destroy instances of your actor at runtime.
149
150    * For managed actors, see `Actor Lifetimes in C++`_.
151    * For top-level actors, see `Creating Top Level Actors From Other Actors`_.
152      The first actor in a process is a very special exception -- see `Creating
153      First Top Level Actors`_.
154#. Write handlers for your actor's messages.  See `Actors and Messages in
155   C++`_.
156#. Start sending messages through your actors!  Again, see `Actors and Messages
157   in C++`_.
158
159The Protocol Language
160---------------------
161
162This document will follow the integration of two actors into Firefox --
163``PMyManager`` and ``PMyManaged``.  ``PMyManager`` will manage ``PMyManaged``.
164A good place to start is with the IPDL actor definitions.  These are files
165that are named for the actor (e.g. ``PMyManager.ipdl``) and that declare the
166messages that a protocol understands.  These actors are for demonstration
167purposes and involve quite a bit of functionality.  Most actors will use a very
168small fraction of these features.
169
170.. literalinclude:: _static/PMyManager.ipdl
171   :language: c++
172   :name: PMyManager.ipdl
173
174.. literalinclude:: _static/PMyManaged.ipdl
175   :language: c++
176   :name: PMyManaged.ipdl
177
178These files reference three additional files.  ``MyTypes.ipdlh`` is an "IPDL
179header" that can be included into ``.ipdl`` files as if it were inline, except
180that it also needs to include any external actors and data types it uses:
181
182.. literalinclude:: _static/MyTypes.ipdlh
183   :language: c++
184   :name: MyTypes.ipdlh
185
186``MyActorUtils.h`` and ``MyDataTypes.h`` are normal C++ header files that
187contain definitions for types passed by these messages, as well as instructions
188for serializing them.  They will be covered in `The C++ Interface`_.
189
190Using The IPDL compiler
191~~~~~~~~~~~~~~~~~~~~~~~
192
193To build IPDL files, list them (alphabetically sorted) in a ``moz.build`` file.
194In this example, the ``.ipdl`` and ``.ipdlh`` files would be alongside a
195``moz.build`` containing:
196
197.. code-block:: c++
198
199    IPDL_SOURCES += [
200        "MyTypes.ipdlh",
201        "PMyManaged.ipdl",
202        "PMyManager.ipdl",
203    ]
204
205    UNIFIED_SOURCES += [
206        "MyManagedChild.cpp",
207        "MyManagedParent.cpp",
208        "MyManagerChild.cpp",
209        "MyManagerParent.cpp",
210    ]
211
212    include("/ipc/chromium/chromium-config.mozbuild")
213
214``chromium-config.mozbuild`` sets up paths so that generated IPDL header files
215are in the proper scope.  If it isn't included, the build will fail with
216``#include`` errors in both your actor code and some internal ipc headers.  For
217example:
218
219.. code-block:: c++
220
221    c:/mozilla-src/mozilla-unified/obj-64/dist/include\ipc/IPCMessageUtils.h(13,10): fatal error: 'build/build_config.h' file not found
222
223``.ipdl`` files are compiled to C++ files as one of the earliest post-configure
224build steps.  Those files are, in turn, referenced throughout the source code
225and build process.  From ``PMyManager.ipdl`` the compiler generates two header
226files added to the build context and exported globally:
227``mozilla/myns/PMyManagerParent.h`` and ``mozilla/myns/PMyManagerChild.h``, as
228discussed in `Namespaces`_ below.  These files contain the base classes for the
229actors.  It also makes several other files, including C++ source files and
230another header, that are automatically included into the build and should not
231require attention.
232
233C++ definions of the actors are required for IPDL.  They define the actions
234that are taken in response to messages -- without this, they would have no
235value.  There will be much more on this when we discuss `Actors and Messages in
236C++`_ but note here that C++ header files named for the actor are required by
237the IPDL `compiler`.  The example would expect
238``mozilla/myns/MyManagedChild.h``, ``mozilla/myns/MyManagedParent.h``,
239``mozilla/myns/MyManagerChild.h`` and ``mozilla/myns/MyManagerParent.h`` and
240will not build without them.
241
242Referencing Externally Defined Data Types: IPDL Includes
243~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
244
245Let's begin with ``PMyManager.ipdl``.  It starts by including types that it
246will need from other places:
247
248.. code-block:: c++
249
250    include protocol PMyManaged;
251    include MyTypes;                          // for MyActorPair
252
253    using MyActorEnum from "mozilla/myns/MyActorUtils.h";
254    using struct mozilla::myns::MyData from "mozilla/MyDataTypes.h";
255    [MoveOnly] using mozilla::myns::MyOtherData from "mozilla/MyDataTypes.h";
256    [RefCounted] using class mozilla::myns::MyThirdData from "mozilla/MyDataTypes.h";
257
258The first line includes a protocol that PMyManager will manage.  That protocol
259is defined in its own ``.ipdl`` file.  Cyclic references are expected and pose
260no concern.
261
262The second line includes the file ``MyTypes.ipdlh``, which defines types like
263structs and unions, but in IPDL, which means they have behavior that goes
264beyond the similar C++ concepts.  Details can be found in `Generating
265IPDL-Aware C++ Data Types: IPDL Structs and Unions`_.
266
267The final lines include types from C++ headers.  Additionally, the [RefCounted]
268and [MoveOnly] attributes tell IPDL that the types have special functionality
269that is important to operations.  These are the data type attributes currently
270understood by IPDL:
271
272================ ==============================================================
273``[RefCounted]`` Type ``T`` is reference counted (by ``AddRef``/``Release``).
274                 As a parameter to a message or as a type in IPDL
275                 structs/unions, it is referenced as a ``RefPtr<T>``.
276``[MoveOnly]``   The type ``T`` is treated as uncopyable.  When used as a
277                 parameter in a message or an IPDL struct/union, it is as an
278                 r-value ``T&&``.
279================ ==============================================================
280
281Finally, note that ``using``, ``using class`` and ``using struct`` are all
282valid syntax.  The ``class`` and ``struct`` keywords are optional.
283
284Namespaces
285~~~~~~~~~~
286
287From the IPDL file:
288
289.. code-block:: c++
290
291    namespace mozilla {
292    namespace myns {
293
294        // ... data type and actor definitions ...
295
296    }    // namespace myns
297    }    // namespace mozilla
298
299
300Namespaces work similar to the way they do in C++.  They also mimic the
301notation, in an attempt to make them comfortable to use.  When IPDL actors are
302compiled into C++ actors, the namespace scoping is carried over.  As previously
303noted, when C++ types are included into IPDL files, the same is true.  The most
304important way in which they differ is that IPDL also uses the namespace to
305establish the path to the generated files.  So, the example defines the IPDL
306data type ``mozilla::myns::MyUnion`` and the actors
307``mozilla::myns::PMyManagerParent`` and  ``mozilla::myns::PMyManagerChild``,
308which can be included from ``mozilla/myns/PMyManagerParent.h``,
309``mozilla/myns/PMyManagerParent.h`` and ``mozilla/myns/PMyManagerChild.h``,
310respectively.  The namespace becomes part of the path.
311
312Generating IPDL-Aware C++ Data Types: IPDL Structs and Unions
313~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
314
315``PMyManager.ipdl`` and ``MyTypes.ipdlh`` define:
316
317.. code-block:: c++
318
319    [Comparable] union MyUnion {
320        float;
321        MyOtherData;
322    };
323
324    struct MyActorPair {
325        PMyManaged actor1;
326        nullable PMyManaged actor2;
327    };
328
329From these descriptions, IPDL generates C++ classes that approximate the
330behavior of C++ structs and unions but that come with pre-defined
331``ParamTraits`` implementations.  These objects can also be used as usual
332outside of IPDL, although the lack of control over the generated code means
333they are sometimes poorly suited to use as plain data.  See `ParamTraits`_ for
334details.
335
336The ``[Comparable]`` attribute tells IPDL to generate ``operator==`` and
337``operator!=`` for the new type.  In order for it to do that, the fields inside
338the new type need to define both of those operators.
339
340Finally, the ``nullable`` keyword indicates that, when serialized, the actor
341may be null.  It is intended to help users avoid null-object dereference
342errors.  It only applies to actor types and may also be attached to parameters
343in message declarations.
344
345Defining Actors
346~~~~~~~~~~~~~~~
347
348The real point of any ``.ipdl`` file is that each defines exactly one actor
349protocol.  The definition always matches the ``.ipdl`` filename.  Repeating the
350one in ``PMyManager.ipdl``:
351
352.. code-block:: c++
353
354    sync protocol PMyManager {
355        manages PMyManaged;
356
357        async PMyManaged();
358        // ... more message declarations ...
359    };
360
361.. important::
362    A form of reference counting is `always` used internally by IPDL to make
363    sure that it and its clients never address an actor the other component
364    deleted but this becomes fragile, and sometimes fails, when the client code
365    does not respect the reference count.  For example, when IPDL detects that
366    a connection died due to a crashed remote process, deleting the actor could
367    leave dangling pointers, so IPDL `cannot` delete it.  On the other hand,
368    there are many cases where IPDL is the only entity to have references to
369    some actors (this is very common for one side of a managed actor) so IPDL
370    `must` delete it.  If all of those objects were reference counted then
371    there would be no complexity here.  Indeed, new actors using
372    ``[ManualDealloc]`` should not be approved without a very compelling
373    reason.  New ``[ManualDealloc]`` actors may soon be forbidden.
374
375The ``sync`` keyword tells IPDL that the actor contains messages that block the
376sender using ``sync`` blocking, so the sending thread waits for a response to
377the message.  There is more on what it and the other blocking modes mean in
378`IPDL messages`_.  For now, just know that this is redundant information whose
379value is primarily in making it easy for other developers to know that there
380are ``sync`` messages defined here.  This list gives preliminary definitions of
381the options for the actor-blocking policy of messages:
382
383======================= =======================================================
384``async``               Actor may contain only asynchronous messages.
385``sync``                Actor has ``async`` capabilities and adds  ``sync``
386                        messages.  ``sync`` messages
387                        can only be sent from the child actor to the parent.
388``intr`` (deprecated)   Actor has ``sync`` capabilities and adds ``intr``
389                        messages.  Some messages can be received while an actor
390                        waits for an ``intr`` response.  This type will be
391                        removed soon.
392======================= =======================================================
393
394Beyond these protocol blocking strategies, IPDL supports annotations that
395indicate the actor has messages that may be received in an order other than
396the one they were sent in.  These orderings attempt to handle messages in
397"message thread" order (as in e.g. mailing lists).  These behaviors can be
398difficult to design for.  Their use is discouraged but is sometimes warranted.
399They will be discussed further in `Nested messages`_.
400
401============================== ================================================
402``[NestedUpTo=inside_sync]``   Actor has high priority messages that can be
403                               handled while waiting for a ``sync`` response.
404``[NestedUpTo=inside_cpow]``   Actor has the highest priority messages that
405                               can be handled while waiting for a ``sync``
406                               response.
407============================== ================================================
408
409The ``manages`` clause tells IPDL that ``PMyManager`` manages the
410``PMyManaged`` actor that was previously ``include`` d.  As with any managed
411protocol, it must also be the case that ``PMyManaged.ipdl`` includes
412``PMyManager`` and declares that ``PMyManaged`` is ``managed`` by
413``PMyManager``.  Recalling the code:
414
415.. code-block:: c++
416
417    // PMyManaged.ipdl
418    include protocol PMyManager;
419    // ...
420
421    protocol PMyManaged {
422      manager PMyManager;
423      // ...
424    };
425
426An actor has a ``manager`` (e.g. ``PMyManaged``) or else it is a top-level
427actor (e.g. ``PMyManager``).  An actor protocol may be managed by more than one
428actor type.  For example, ``PMyManaged`` could have also been managed by some
429``PMyOtherManager`` not shown here.  In that case, ``manager`` s are presented
430in a list, separated by ``or`` -- e.g. ``manager PMyManager or
431PMyOtherManager``.  Of course, an **instance** of a managed actor type has only
432one manager actor (and is therefore managed by only one of the types of
433manager).  The manager of an instance of a managee is always the actor that
434constructed that managee.
435
436Finally, there is the message declaration ``async PMyManaged()``.  This message
437is a constructor for ``MyManaged`` actors; unlike C++ classes, it is found in
438``MyManager``.  Every manager will need to expose constructors to create its
439managed types.  These constructors are the only way to create an actor that is
440managed.  They can take parameters and return results, like normal messages.
441The implementation of IPDL constructors are discussed in `Actor Lifetimes in
442C++`_.
443
444We haven't discussed a way to construct new top level actors.  This is a more
445advanced topic and is covered separately in `Top Level Actors`_.
446
447.. _IPDL messages: `Declaring IPDL Messages`_
448
449Declaring IPDL Messages
450~~~~~~~~~~~~~~~~~~~~~~~
451
452The final part of the actor definition is the declaration of messages:
453
454.. code-block:: c++
455
456    sync protocol PMyManager {
457      // ...
458      parent:
459        async __delete__(nsString aNote);
460        sync SomeMsg(MyActorPair? aActors, MyData[] aMyData)
461            returns (int32_t x, int32_t y, MyUnion aUnion);
462        async PMyManaged();
463      both:
464        [Tainted] async AnotherMsg(MyActorEnum aEnum, int32_t aNumber)
465            returns (MyOtherData aOtherData);
466    };
467
468The messages are grouped into blocks by ``parent:``, ``child:`` and ``both:``.
469These labels work the way ``public:`` and ``private:`` work in C++ -- messages
470after these descriptors are sent/received (only) in the direction specified.
471
472.. note::
473    As a mnemonic to remember which direction they indicate, remember to put
474    the word "to" in front of them.  So, for example, ``parent:`` preceeds
475    ``__delete__``, meaning ``__delete__`` is sent from the child **to** the
476    parent, and ``both:`` states that ``AnotherMsg`` can be sent **to** either
477    endpoint.
478
479IPDL messages support the following annotations:
480
481======================== ======================================================
482``[Compress]``           Indicates repeated messages of this type will
483                         consolidate.
484``[Tainted]``            Parameters are required to be validated before using
485                         them.
486``[Priority=Foo]``       Priority of ``MessageTask`` that runs the C++ message
487                         handler.  ``Foo`` is one of: ``normal``, ``input``,
488                         ``vsync``, ``mediumhigh``, or ``control``.
489                         See the ``IPC::Message::PriorityValue`` enum.
490``[Nested=inside_sync]`` Indicates that the message can sometimes be handled
491                         while a sync message waits for a response.
492``[Nested=inside_cpow]`` Indicates that the message can sometimes be handled
493                         while a sync message waits for a response.
494======================== ======================================================
495
496``[Compress]`` provides crude protection against spamming with a flood of
497messages.  When messages of type ``M`` are compressed, the queue of unprocessed
498messages between actors will never contain an ``M`` beside another one; they
499will always be separated by a message of a different type.  This is achieved by
500throwing out the older of the two messages if sending the new one would break
501the rule.  This has been used to throttle pointer events between the main and
502content processes.
503
504``[Compress=all]`` is similar but applies whether or not the messages are
505adjacent in the message queue.
506
507``[Tainted]`` is a C++ mechanism designed to encourage paying attentiton to
508parameter security.  The values of tainted parameters cannot be used until you
509vouch for their safety.  They are discussed in `Actors and Messages in C++`_.
510
511The ``Nested`` annotations are deeply related to the message's blocking policy
512that follows it and which was briefly discussed in `Defining Actors`_.  See
513`Nested messages`_ for details.
514
515The following is a complete list of the available blocking policies.  It
516resembles the list in `Defining Actors`_:
517
518====================== ========================================================
519``async``              Actor may contain only asynchronous messages.
520``sync``               Actor has ``async`` capabilities and adds  ``sync``
521                       messages.  ``sync`` messages can only be sent from the
522                       child actor to the parent.
523``intr`` (deprecated)  Actor has ``sync`` capabilities and adds ``intr``
524                       messages.  This type will be removed soon.
525====================== ========================================================
526
527The policy defines whether an actor will wait for a response when it sends a
528certain type of message.  A ``sync`` actor will wait immediately after sending
529a ``sync`` message, stalling its thread, until a response is received.  This is
530an easy source of browser stalls.  It is rarely required that a message be
531synchronous.  New ``sync`` messages are therefore required to get approval from
532an IPC peer.  The IPDL compiler will require such messages to be listed in the
533file ``sync-messages.ini``.
534
535The notion that only child actors can send ``sync`` messages was introduced to
536avoid potential deadlocks.  It relies on the belief that a cycle (deadlock) of
537sync messages is impossible because they all point in one direction.  This is
538no longer the case because any endpoint can be a child `or` parent and some,
539like the main process, sometimes serve as both.  This means that sync messages
540should be used with extreme care.
541
542.. note::
543    The notion of sync messages flowing in one direction is still the main
544    mechanism IPDL uses to avoid deadlock.  New actors should avoid violating
545    this rule as the consequences are severe (and complex).  Actors that break
546    these rules should not be approved without **extreme** extenuating
547    circumstances.  If you think you need this, check with the IPC team on
548    Element first (#ipc).
549
550An ``async`` actor will not wait.  An ``async`` response is essentially
551identical to sending another ``async`` message back.  It may be handled
552whenever received messages are handled.  The value over an ``async`` response
553message comes in the ergonomics -- async responses are usually handled by C++
554lambda functions that are more like continuations than methods.  This makes
555them easier to write and to read.  Additionally, they allow a response to
556return message failure, while there would be no such response if we were
557expecting to send a new async message back, and it failed.
558
559Following synchronization is the name of the message and its parameter list.
560The message ``__delete__`` stands out as strange -- indeed, it terminates the
561actor's connection.  `It does not delete any actor objects itself!`  It severs
562the connections of the actor `and any actors it manages` at both endpoints.  An
563actor will never send or receive any messages after it sends or receives a
564``__delete__``.  Note that all sends and receives have to happen on a specific
565*worker* thread for any actor tree so the send/receive order is well defined.
566Anything sent after the actor processes ``__delete__`` is ignored (send returns
567an error, messages yet to be received fail their delivery).  In other words,
568some future operations may fail but no unexpected behavior is possible.
569
570In our example, the child can break the connection by sending ``__delete__`` to
571the parent.  The only thing the parent can do to sever the connection is to
572fail, such as by crashing.  This sort of unidirectional control is both common
573and desirable.
574
575``PMyManaged()`` is a managed actor constructor.  Note the asymmetry -- an
576actor contains its managed actor's constructors but its own destructor.
577
578The list of parameters to a message is fairly straight-forward.  Parameters
579can be any type that has a C++ ``ParamTraits`` specialization and is imported
580by a directive.  That said, there are some surprises in the list of messages:
581
582================= =============================================================
583``int32_t``,...   The standard primitive types are included.  See `builtin.py`_
584                  for a list.  Pointer types are, unsurprisingly, forbidden.
585``?``             When following a type T, the parameter is translated into
586                  ``Maybe<T>`` in C++.
587``[]``            When following a type T, the parameter is translated into
588                  ``nsTArray<T>`` in C++.
589================= =============================================================
590
591Finally, the returns list declares the information sent in response, also as a
592tuple of typed parameters.  As previously mentioned, even ``async`` messages
593can receive responses.  A ``sync`` message will always wait for a response but
594an ``async`` message will not get one unless it has a ``returns`` clause.
595
596This concludes our tour of the IPDL example file.  The connection to C++ is
597discussed in the next chapter; messages in particular are covered in `Actors
598and Messages in C++`_.  For suggestions on best practices when designing your
599IPDL actor approach, see `IPDL Best Practices`_.
600
601.. _builtin.py: https://searchfox.org/mozilla-central/source/ipc/ipdl/ipdl/builtin.py
602
603IPDL Syntax Quick Reference
604~~~~~~~~~~~~~~~~~~~~~~~~~~~
605
606The following is a list of the keywords and operators that have been introduced
607for use in IPDL files:
608
609============================= =================================================
610``include``                   Include a C++ header (quoted file name) or
611                              ``.ipdlh`` file (unquoted with no file suffix).
612``using (class|struct) from`` Similar to ``include`` but imports only a
613                              specific data type.
614``include protocol``          Include another actor for use in management
615                              statements, IPDL data types or as parameters to
616                              messages.
617``[RefCounted]``              Indicates that the imported C++ data types are
618                              reference counted. Refcounted types require a
619                              different ``ParamTraits`` interface than
620                              non-reference-counted types.
621``[ManualDealloc]``           Indicates that the IPDL interface uses the legacy
622                              manual allocation/deallocation interface, rather
623                              than modern reference counting.
624``[MoveOnly]``                Indicates that an imported C++ data type should
625                              not be copied.  IPDL code will move it instead.
626``namespace``                 Specifies the namespace for IPDL generated code.
627``union``                     An IPDL union definition.
628``struct``                    An IPDL struct definition.
629``[Comparable]``              Indicates that IPDL should generate
630                              ``operator==`` and ``operator!=`` for the given
631                              IPDL struct/union.
632``nullable``                  Indicates that an actor reference in an IPDL type
633                              may be null when sent over IPC.
634``protocol``                  An IPDL protocol (actor) definition.
635``sync/async``                These are used in two cases: (1) to indicate
636                              whether a message blocks as it waits for a result
637                              and (2) because an actor that contains ``sync``
638                              messages must itself be labeled ``sync`` or
639                              ``intr``.
640``[NestedUpTo=inside_sync]``  Indicates that an actor contains
641                              [Nested=inside_sync] messages, in addition to
642                              normal messages.
643``[NestedUpTo=inside_cpow]``  Indicates that an actor contains
644                              [Nested=inside_cpow] messages, in addition to
645                              normal messages.
646``intr``                      Used to indicate either that (1) an actor
647                              contains ``sync``, ``async`` and (deprecated)
648                              ``intr`` messages, or (2) a message is ``intr``
649                              type.
650``[Nested=inside_sync]``      Indicates that the message can be handled while
651                              waiting for lower-priority, or in-message-thread,
652                              sync responses.
653``[Nested=inside_cpow]``      Indicates that the message can be handled while
654                              waiting for lower-priority, or in-message-thread,
655                              sync responses.  Cannot be sent by the parent
656                              actor.
657``manager``                   Used in a protocol definition to indicate that
658                              this actor manages another one.
659``manages``                   Used in a protocol definition to indicate that
660                              this actor is managed by another one.
661``or``                        Used in a ``manager`` clause for actors that have
662                              multiple potential managers.
663``parent: / child: / both:``  Indicates direction of subsequent actor messages.
664                              As a mnemonic to remember which direction they
665                              indicate, put the word "to" in front of them.
666``returns``                   Defines return values for messages.  All types
667                              of message, including ``async``, support
668                              returning values.
669``__delete__``                A special message that destroys the related
670                              actors at both endpoints when sent.
671                              ``Recv__delete__`` and ``ActorDestroy`` are
672                              called before destroying the actor at the other
673                              endpoint, to allow for cleanup.
674``int32_t``,...               The standard primitive types are included.
675``String``                    Translated into ``nsString`` in C++.
676``?``                         When following a type T in an IPDL data structure
677                              or message parameter,
678                              the parameter is translated into ``Maybe<T>`` in
679                              C++.
680``[]``                        When following a type T in an IPDL data structure
681                              or message parameter,
682                              the parameter is translated into ``nsTArray<T>``
683                              in C++.
684``[Tainted]``                 Used to indicate that a message's handler should
685                              receive parameters that it is required to
686                              manually validate.  Parameters of type ``T``
687                              become ``Tainted<T>`` in C++.
688``[Compress]``                Indicates repeated messages of this type will
689                              consolidate.  When two messages of this type are
690                              sent and end up side-by-side in the message queue
691                              then the older message is discarded (not sent).
692``[Compress=all]``            Like ``[Compress]`` but discards the older
693                              message regardless of whether they are adjacent
694                              in the message queue.
695``[Priority=Foo]``            Priority of ``MessageTask`` that runs the C++
696                              message handler.  ``Foo`` is one of: ``normal``,
697                              ``input``, ``vsync``, ``mediumhigh``, or
698                              ``control``.
699``[ChildImpl="RemoteFoo"]``   Indicates that the child side implementation of
700                              the actor is a class named ``RemoteFoo``, and the
701                              definition is included by one of the
702                              ``include "...";`` statements in the file.
703                              *New uses of this attribute are discouraged.*
704``[ParentImpl="FooImpl"]``    Indicates that the parent side implementation of
705                              the actor is a class named ``FooImpl``, and the
706                              definition is included by one of the
707                              ``include "...";`` statements in the file.
708                              *New uses of this attribute are discouraged.*
709``[ChildImpl=virtual]``       Indicates that the child side implementation of
710                              the actor is not exported by a header, so virtual
711                              ``Recv`` methods should be used instead of direct
712                              function calls.  *New uses of this attribute are
713                              discouraged.*
714``[ParentImpl=virtual]``      Indicates that the parent side implementation of
715                              the actor is not exported by a header, so virtual
716                              ``Recv`` methods should be used instead of direct
717                              function calls.  *New uses of this attribute are
718                              discouraged.*
719============================= =================================================
720
721
722The C++ Interface
723-----------------
724
725ParamTraits
726~~~~~~~~~~~
727
728Before discussing how C++ represents actors and messages, we look at how IPDL
729connects to the imported C++ data types.  In order for any C++ type to be
730(de)serialized, it needs an implementation of the ``ParamTraits`` C++ type
731class.  ``ParamTraits`` is how your code tells IPDL what bytes to write to
732serialize your objects for sending, and how to convert those bytes back to
733objects at the other endpoint.  Since ``ParamTraits`` need to be reachable by
734IPDL code, they need to be declared in a C++ header and imported by your
735protocol file.  Failure to do so will result in a build error.
736
737Most basic types and many essential Mozilla types are always available for use
738without inclusion.  An incomplete list includes: C++ primitives, strings
739(``std`` and ``mozilla``), vectors (``std`` and ``mozilla``), ``RefPtr<T>``
740(for serializable ``T``), ``UniquePtr<T>``, ``nsCOMPtr<T>``, ``nsTArray<T>``,
741``std::unordered_map<T>``, ``nsresult``, etc.  See `builtin.py
742<https://searchfox.org/mozilla-central/source/ipc/ipdl/ipdl/builtin.py>`_,
743`ipc_message_utils.h
744<https://searchfox.org/mozilla-central/source/ipc/chromium/src/chrome/common/ipc_message_utils.h>`_
745and `IPCMessageUtilsSpecializations.h
746<https://searchfox.org/mozilla-central/source/ipc/glue/IPCMessageUtilsSpecializations.h>`_.
747
748``ParamTraits`` typically bootstrap with the ``ParamTraits`` of more basic
749types, until they hit bedrock (e.g. one of the basic types above).  In the most
750extreme cases, a ``ParamTraits`` author may have to resort to designing a
751binary data format for a type.  Both options are available.
752
753We haven't seen any of this C++ yet.  Let's look at the data types included
754from ``MyDataTypes.h``:
755
756.. code-block:: c++
757
758    // MyDataTypes.h
759    namespace mozilla::myns {
760        struct MyData {
761            nsCString s;
762            uint8_t bytes[17];
763            MyData();      // IPDL requires the default constructor to be public
764        };
765
766        struct MoveonlyData {
767            MoveonlyData();
768            MoveonlyData& operator=(const MoveonlyData&) = delete;
769
770            MoveonlyData(MoveonlyData&& m);
771            MoveonlyData& operator=(MoveonlyData&& m);
772        };
773
774        typedef MoveonlyData MyOtherData;
775
776        class MyUnusedData {
777        public:
778            NS_INLINE_DECL_REFCOUNTING(MyUnusedData)
779            int x;
780        };
781    };
782
783    namespace IPC {
784        // Basic type
785        template<>
786        struct ParamTraits<mozilla::myns::MyData> {
787            typedef mozilla::myns::MyData paramType;
788            static void Write(MessageWriter* m, const paramType& in);
789            static bool Read(MessageReader* m, paramType* out);
790        };
791
792        // [MoveOnly] type
793        template<>
794        struct ParamTraits<mozilla::myns::MyOtherData> {
795            typedef mozilla::myns::MyOtherData paramType;
796            static void Write(MessageWriter* m, const paramType& in);
797            static bool Read(MessageReader* m, paramType* out);
798        };
799
800        // [RefCounted] type
801        template<>
802        struct ParamTraits<mozilla::myns::MyUnusedData*> {
803            typedef mozilla::myns::MyUnusedData paramType;
804            static void Write(MessageWriter* m, paramType* in);
805            static bool Read(MessageReader* m, RefPtr<paramType>* out);
806        };
807    }
808
809MyData is a struct and MyOtherData is a typedef.  IPDL is fine with both.
810Additionally, MyOtherData is not copyable, matching its IPDL ``[MoveOnly]``
811annotation.
812
813``ParamTraits`` are required to be defined in the ``IPC`` namespace.  They must
814contain a ``Write`` method with the proper signature that is used for
815serialization and a ``Read`` method, again with the correct signature, for
816deserialization.
817
818Here we have three examples of declarations: one for an unannotated type, one
819for ``[MoveOnly]`` and a ``[RefCounted]`` one.  Notice the difference in the
820``[RefCounted]`` type's method signatures.  The only difference that may not be
821clear from the function types is that, in the non-reference-counted case, a
822default-constructed object is supplied to ``Read`` but, in the
823reference-counted case, ``Read`` is given an empty ``RefPtr<MyUnusedData>`` and
824should only allocate a ``MyUnusedData`` to return if it so desires.
825
826These are straight-forward implementations of the ``ParamTraits`` methods for
827``MyData``:
828
829.. code-block:: c++
830
831    /* static */ void IPC::ParamTraits<MyData>::Write(MessageWriter* m, const paramType& in) {
832        WriteParam(m, in.s);
833        m->WriteBytes(in.bytes, sizeof(in.bytes));
834    }
835    /* static */ bool IPC::ParamTraits<MyData>::Read(MessageReader* m, paramType* out) {
836        return ReadParam(m, &out->s) &&
837               m->ReadBytesInto(out->bytes, sizeof(out->bytes));
838    }
839
840``WriteParam`` and ``ReadParam`` call the ``ParamTraits`` for the data you pass
841them, determined using the type of the object as supplied.  ``WriteBytes`` and
842``ReadBytesInto`` work on raw, contiguous bytes as expected.  ``MessageWriter``
843and ``MessageReader`` are IPDL internal objects which hold the incoming/outgoing
844message as a stream of bytes and the current spot in the stream.  It is *very*
845rare for client code to need to create or manipulate these obejcts. Their
846advanced use is beyond the scope of this document.
847
848.. important::
849    Potential failures in ``Read`` include everyday C++ failures like
850    out-of-memory conditions, which can be handled as usual.  But ``Read`` can
851    also fail due to things like data validation errors.  ``ParamTraits`` read
852    data that is considered insecure.  It is important that they catch
853    corruption and properly handle it.  Returning false from ``Read`` will
854    usually result in crashing the process (everywhere except in the main
855    process).  This is the right behavior as the browser would be in an
856    unexpected state, even if the serialization failure was not malicious
857    (since it cannot process the message).  Other responses, such as failing
858    with a crashing assertion, are inferior.  IPDL fuzzing relies on
859    ``ParamTraits`` not crashing due to corruption failures.
860    Occasionally, validation will require access to state that ``ParamTraits``
861    can't easily reach.  (Only) in those cases, validation can be reasonably
862    done in the message handler.  Such cases are a good use of the ``Tainted``
863    annotation.  See `Actors and Messages in C++`_ for more.
864
865.. note::
866    In the past, it was required to specialize ``mozilla::ipc::IPDLParamTraits<T>``
867    instead of ``IPC::ParamTraits<T>`` if you needed the actor object itself during
868    serialization or deserialization. These days the actor can be fetched using
869    ``IPC::Message{Reader,Writer}::GetActor()`` in ``IPC::ParamTraits``, so that
870    trait should be used for all new serializations.
871
872A special case worth mentioning is that of enums.  Enums are a common source of
873security holes since code is rarely safe with enum values that are not valid.
874Since data obtained through IPDL messages should be considered tainted, enums
875are of principal concern.  ``ContiguousEnumSerializer`` and
876``ContiguousEnumSerializerInclusive`` safely implement ``ParamTraits`` for
877enums that are only valid for a contiguous set of values, which is most of
878them.  The generated ``ParamTraits`` confirm that the enum is in valid range;
879``Read`` will return false otherwise.  As an example, here is the
880``MyActorEnum`` included from ``MyActorUtils.h``:
881
882.. code-block:: c++
883
884    enum MyActorEnum { e1, e2, e3, e4, e5 };
885
886    template<>
887    struct ParamTraits<MyActorEnum>
888      : public ContiguousEnumSerializerInclusive<MyActorEnum, MyActorEnum::e1, MyActorEnum::e5> {};
889
890IPDL Structs and Unions in C++
891~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
892
893IPDL structs and unions become C++ classes that provide interfaces that are
894fairly self-explanatory.  Recalling ``MyUnion`` and ``MyActorPair`` from
895`IPDL Structs and Unions`_ :
896
897.. code-block:: c++
898
899    union MyUnion {
900        float;
901        MyOtherData;
902    };
903
904    struct MyActorPair {
905        PMyManaged actor1;
906        nullable PMyManaged actor2;
907    };
908
909These compile to:
910
911.. code-block:: c++
912
913    class MyUnion {
914        enum Type { Tfloat, TMyOtherData };
915        Type type();
916        MyUnion(float f);
917        MyUnion(MyOtherData&& aOD);
918        MyUnion& operator=(float f);
919        MyUnion& operator=(MyOtherData&& aOD);
920        operator float&();
921        operator MyOtherData&();
922    };
923
924    class MyActorPair {
925        MyActorPair(PMyManagedParent* actor1Parent, PMyManagedChild* actor1Child,
926                    PMyManagedParent* actor2Parent, PMyManagedChild* actor2Child);
927        // Exactly one of { actor1Parent(), actor1Child() } must be non-null.
928        PMyManagedParent*& actor1Parent();
929        PMyManagedChild*& actor1Child();
930        // As nullable, zero or one of { actor2Parent(), actor2Child() } will be non-null.
931        PMyManagedParent*& actor2Parent();
932        PMyManagedChild*& actor2Child();
933    }
934
935The generated ``ParamTraits`` use the ``ParamTraits`` for the types referenced
936by the IPDL struct or union.  Fields respect any annotations for their type
937(see `IPDL Includes`_).  For example, a ``[RefCounted]`` type ``T`` generates
938``RefPtr<T>`` fields.
939
940Note that actor members result in members of both the parent and child actor
941types, as seen in ``MyActorPair``.  When actors are used to bridge processes,
942only one of those could ever be used at a given endpoint.  IPDL makes sure
943that, when you send one type (say, ``PMyManagedChild``), the adjacent actor of
944the other type (``PMyManagedParent``) is received.  This is not only true for
945message parameters and IPDL structs/unions but also for custom ``ParamTraits``
946implementations.  If you ``Write`` a ``PFooParent*`` then you must ``Read`` a
947``PFooChild*``.  This is hard to confuse in message handlers since they are
948members of a class named for the side they operate on, but this cannot be
949enforced by the compiler.  If you are writing
950``MyManagerParent::RecvSomeMsg(Maybe<MyActorPair>&& aActors, nsTArray<MyData>&& aMyData)``
951then the ``actor1Child`` and ``actor2Child`` fields cannot be valid since the
952child (usually) exists in another process.
953
954.. _IPDL Structs and Unions: `Generating IPDL-Aware C++ Data Types: IPDL Structs and Unions`_
955.. _IPDL Includes: `Referencing Externally Defined Data Types: IPDL Includes`_
956
957Actors and Messages in C++
958~~~~~~~~~~~~~~~~~~~~~~~~~~
959
960As mentioned in `Using The IPDL compiler`_, the IPDL compiler generates two
961header files for the protocol ``PMyManager``: ``PMyManagerParent.h`` and
962``PMyManagerChild.h``, which declare the actor's base classes.  There, we
963discussed how the headers are visible to C++ components that include
964``chromium-config.mozbuild``.  We, in turn, always need to define two files
965that declare our actor implementation subclasses (``MyManagerParent.h`` and
966``MyManagerChild.h``).  The IPDL file looked like this:
967
968.. literalinclude:: _static/PMyManager.ipdl
969   :language: c++
970   :name: PMyManager.ipdl
971
972So ``MyManagerParent.h`` looks like this:
973
974.. code-block:: c++
975
976    #include "PMyManagerParent.h"
977
978    namespace mozilla {
979    namespace myns {
980
981    class MyManagerParent : public PMyManagerParent {
982        NS_INLINE_DECL_REFCOUNTING(MyManagerParent, override)
983    protected:
984        IPCResult Recv__delete__(const nsString& aNote);
985        IPCResult RecvSomeMsg(const Maybe<MyActorPair>& aActors, const nsTArray<MyData>& aMyData,
986                              int32_t* x, int32_t* y, MyUnion* aUnion);
987        IPCResult RecvAnotherMsg(const Tainted<MyActorEnum>& aEnum, const Tainted<int32_t>& aNumber,
988                                 AnotherMsgResolver&& aResolver);
989
990        already_AddRefed<PMyManagerParent> AllocPMyManagedParent();
991        IPCResult RecvPMyManagedConstructor(PMyManagedConstructor* aActor);
992
993        // ... etc ...
994    };
995
996    } // namespace myns
997    } // namespace mozilla
998
999All messages that can be sent to the actor must be handled by ``Recv`` methods
1000in the proper actor subclass.  They should return ``IPC_OK()`` on success and
1001``IPC_FAIL(actor, reason)`` if an error occurred (where ``actor`` is ``this``
1002and ``reason`` is a human text explanation) that should be considered a failure
1003to process the message.  The handling of such a failure is specific to the
1004process type.
1005
1006``Recv`` methods are called by IPDL by enqueueing a task to run them on the
1007``MessageLoop`` for the thread on which they are bound.  This thread is the
1008actor's *worker thread*.  All actors in a managed actor tree have the same
1009worker thread -- in other words, actors inherit the worker thread from their
1010managers.  Top level actors establish their worker thread when they are
1011*bound*.  More information on threads can be found in `Top Level Actors`_.  For
1012the most part, client code will never engage with an IPDL actor outside of its
1013worker thread.
1014
1015Received parameters become stack variables that are ``std::move``-d into the
1016``Recv`` method.  They can be received as a const l-value reference,
1017rvalue-reference, or by value (type-permitting).  ``[MoveOnly]`` types should
1018not be received as const l-values.  Return values for sync messages are
1019assigned by writing to non-const (pointer) parameters.  Return values for async
1020messages are handled differently -- they are passed to a resolver function.  In
1021our example, ``AnotherMsgResolver`` would be a ``std::function<>`` and
1022``aResolver`` would be given the value to return by passing it a reference to a
1023``MyOtherData`` object.
1024
1025``MyManagerParent`` is also capable of ``sending`` an async message that
1026returns a value: ``AnotherMsg``.  This is done with ``SendAnotherMsg``, which
1027is defined automatically by IPDL in the base class ``PMyManagerParent``.  There
1028are two signatures for ``Send`` and they look like this:
1029
1030.. code-block:: c++
1031
1032    // Return a Promise that IPDL will resolve with the response or reject.
1033    RefPtr<MozPromise<MyOtherData, ResponseRejectReason, true>>
1034    SendAnotherMsg(const MyActorEnum& aEnum, int32_t aNumber);
1035
1036    // Provide callbacks to process response / reject.  The callbacks are just
1037    // std::functions.
1038    void SendAnotherMsg(const MyActorEnum& aEnum, int32_t aNumber,
1039        ResolveCallback<MyOtherData>&& aResolve, RejectCallback&& aReject);
1040
1041The response is usually handled by lambda functions defined at the site of the
1042``Send`` call, either by attaching them to the returned promise with e.g.
1043``MozPromise::Then``, or by passing them as callback parameters.  See docs on
1044``MozPromise`` for more on its use.  The promise itself is either resolved or
1045rejected by IPDL when a valid reply is received or when the endpoint determines
1046that the communication failed.  ``ResponseRejectReason`` is an enum IPDL
1047provides to explain failures.
1048
1049Additionally, the ``AnotherMsg`` handler has ``Tainted`` parameters, as a
1050result of the [Tainted] annotation in the protocol file.  Recall that
1051``Tainted`` is used to force explicit validation of parameters in the message
1052handler before their values can be used (as opposed to validation in
1053``ParamTraits``).  They therefore have access to any state that the message
1054handler does.  Their APIs, along with a list of macros that are used to
1055validate them, are detailed `here
1056<https://searchfox.org/mozilla-central/source/mfbt/Tainting.h>`__.
1057
1058Send methods that are not for async messages with return values follow a
1059simpler form; they return a ``bool`` indicating success or failure and return
1060response values in non-const parameters, as the ``Recv`` methods do.  For
1061example, ``PMyManagerChild`` defines this to send the sync message ``SomeMsg``:
1062
1063.. code-block:: c++
1064
1065    // generated in PMyManagerChild
1066    bool SendSomeMsg(const Maybe<MyActorPair>& aActors, const nsTArray<MyData>& aMyData,
1067                     int32_t& x, int32_t& y, MyUnion& aUnion);
1068
1069Since it is sync, this method will not return to its caller until the response
1070is received or an error is detected.
1071
1072All calls to ``Send`` methods, like all messages handler ``Recv`` methods, must
1073only be called on the worker thread for the actor.
1074
1075Constructors, like the one for ``MyManaged``, are clearly an exception to these
1076rules.  They are discussed in the next section.
1077
1078.. _Actor Lifetimes in C++:
1079
1080Actor Lifetimes in C++
1081~~~~~~~~~~~~~~~~~~~~~~
1082
1083The constructor message for ``MyManaged`` becomes *two* methods at the
1084receiving end.  ``AllocPMyManagedParent`` constructs the managed actor, then
1085``RecvPMyManagedConstructor`` is called to update the new actor.  The following
1086diagram shows the construction of the ``MyManaged`` actor pair:
1087
1088.. mermaid::
1089    :align: center
1090    :caption: A ``MyManaged`` actor pair being created by some ``Driver``
1091              object.  Internal IPC objects in the parent and child processes
1092              are combined for compactness.  Connected **par** blocks run
1093              concurrently.  This shows that messages can be safely sent while
1094              the parent is still being constructed.
1095
1096    %%{init: {'sequence': {'boxMargin': 4, 'actorMargin': 10} }}%%
1097    sequenceDiagram
1098        participant d as Driver
1099        participant mgdc as MyManagedChild
1100        participant mgrc as MyManagerChild
1101        participant ipc as IPC Child/Parent
1102        participant mgrp as MyManagerParent
1103        participant mgdp as MyManagedParent
1104        d->>mgdc: new
1105        mgdc->>d: [mgd_child]
1106        d->>mgrc: SendPMyManagedConstructor<br/>[mgd_child, params]
1107        mgrc->>ipc: Form actor pair<br/>[mgd_child, params]
1108        par
1109        mgdc->>ipc: early PMyManaged messages
1110        and
1111        ipc->>mgrp: AllocPMyManagedParent<br/>[params]
1112        mgrp->>mgdp: new
1113        mgdp->>mgrp: [mgd_parent]
1114        ipc->>mgrp: RecvPMyManagedConstructor<br/>[mgd_parent, params]
1115        mgrp->>mgdp: initialization
1116        ipc->>mgdp: early PMyManaged messages
1117        end
1118        Note over mgdc,mgdp: Bi-directional sending and receiving will now happen concurrently.
1119
1120The next diagram shows the destruction of the ``MyManaged`` actor pair, as
1121initiated by a call to ``Send__delete__``.  ``__delete__`` is sent from the
1122child process because that is the only side that can call it, as declared in
1123the IPDL protocol file.
1124
1125.. mermaid::
1126    :align: center
1127    :caption: A ``MyManaged`` actor pair being disconnected due to some
1128              ``Driver`` object in the child process sending ``__delete__``.
1129
1130    %%{init: {'sequence': {'boxMargin': 4, 'actorMargin': 10} }}%%
1131    sequenceDiagram
1132        participant d as Driver
1133        participant mgdc as MyManagedChild
1134        participant ipc as IPC Child/Parent
1135        participant mgdp as MyManagedParent
1136        d->>mgdc: Send__delete__
1137        mgdc->>ipc: Disconnect<br/>actor pair
1138        par
1139        ipc->>mgdc: ActorDestroy
1140        ipc->>mgdc: Release
1141        and
1142        ipc->>mgdp: Recv__delete__
1143        ipc->>mgdp: ActorDestroy
1144        ipc->>mgdp: Release
1145        end
1146
1147Finally, let's take a look at the behavior of an actor whose peer has been lost
1148(e.g. due to a crashed process).
1149
1150.. mermaid::
1151    :align: center
1152    :caption: A ``MyManaged`` actor pair being disconnected when its peer is
1153              lost due to a fatal error.  Note that ``Recv__delete__`` is not
1154              called.
1155
1156    %%{init: {'sequence': {'boxMargin': 4, 'actorMargin': 10} }}%%
1157    sequenceDiagram
1158        participant mgdc as MyManagedChild
1159        participant ipc as IPC Child/Parent
1160        participant mgdp as MyManagedParent
1161        Note over mgdc: CRASH!!!
1162        ipc->>ipc: Notice fatal error.
1163        ipc->>mgdp: ActorDestroy
1164        ipc->>mgdp: Release
1165
1166The ``Alloc`` and ``Recv...Constructor`` methods are somewhat mirrored by
1167``Recv__delete__`` and ``ActorDestroy`` but there are a few differences.
1168First, the ``Alloc`` method really does create the actor but the
1169``ActorDestroy`` method does not delete it.  Additionally, ``ActorDestroy``
1170is run at *both* endpoints, during ``Send__delete__`` or after
1171``Recv__delete__``.  Finally and most importantly, ``Recv__delete__`` is only
1172called if the ``__delete__`` message is received but it may not be if, for
1173example, the remote process crashes.  ``ActorDestroy``, on the other hand, is
1174guaranteed to run for *every* actor unless the process terminates uncleanly.
1175For this reason, ``ActorDestroy`` is the right place for most actor shutdown
1176code.  ``Recv__delete__`` is rarely useful, although it is occasionally
1177beneficial to have it receive some final data.
1178
1179The relevant part of the parent class looks like this:
1180
1181.. code-block:: c++
1182
1183    class MyManagerParent : public PMyManagerParent {
1184        already_AddRefed<PMyManagerParent> AllocPMyManagedParent();
1185        IPCResult RecvPMyManagedConstructor(PMyManagedConstructor* aActor);
1186
1187        IPCResult Recv__delete__(const nsString& aNote);
1188        void ActorDestroy(ActorDestroyReason why);
1189
1190        // ... etc ...
1191    };
1192
1193The ``Alloc`` method is required for managed actors that are constructed by
1194IPDL receiving a ``Send`` message.  It is not required for the actor at the
1195endpoint that calls ``Send``.  The ``Recv...Constructor`` message is not
1196required -- it has a base implementation that does nothing.
1197
1198If the constructor message has parameters, they are sent to both methods.
1199Parameters are given to the ``Alloc`` method by const reference but are moved
1200into the ``Recv`` method.  They differ in that messages can be sent from the
1201``Recv`` method but, in ``Alloc``, the newly created actor is not yet
1202operational.
1203
1204The ``Send`` method for a constructor is similarly different from other
1205``Send`` methods.  In the child actor, ours looks like this:
1206
1207.. code-block:: c++
1208
1209    IPCResult SendPMyManagedConstructor(PMyManagedChild* aActor);
1210
1211The method expects a ``PMyManagedChild`` that the caller will have constructed,
1212presumably using ``new`` (this is why it does not require an ``Alloc`` method).
1213Once ``Send...Constructor`` is called, the actor can be used to send and
1214receive messages.  It does not matter that the remote actor may not have been
1215created yet due to asynchronicity.
1216
1217The destruction of actors is as unusual as their construction.  Unlike
1218construction, it is the same for managed and top-level actors.  Avoiding
1219``[ManualDealloc]`` actors removes a lot of the complexity but there is still
1220a process to understand.  Actor destruction begins when an ``__delete__``
1221message is sent.  In ``PMyManager``, this message is declared from child to
1222parent.  The actor calling ``Send__delete__`` is no longer connected to
1223anything when the method returns.  Future calls to ``Send`` return an error
1224and no future messages will be received.  This is also the case for an actor
1225that has run ``Recv__delete__``; it is no longer connected to the other
1226endpoint.
1227
1228.. note::
1229    Since ``Send__delete__`` may release the final reference to itself, it
1230    cannot safely be a class instance method.  Instead, unlike other ``Send``
1231    methods, it's a ``static`` class method and takes the actor as a parameter:
1232
1233    .. code-block:: c++
1234
1235        static IPCResult Send__delete__(PMyManagerChild* aToDelete);
1236
1237    Additionally, the ``__delete__`` message tells IPDL to disconnect both the
1238    given actor *and all of its managed actors*.  So it is really deleting the
1239    actor subtree, although ``Recv__delete__`` is only called for the actor it
1240    was sent to.
1241
1242During the call to ``Send__delete__``, or after the call to ``Recv__delete__``,
1243the actor's ``ActorDestroy`` method is called.  This method gives client code a
1244chance to do any teardown that must happen in `all` circumstances were it is
1245possible -- both expected and unexpected.  This means that ``ActorDestroy``
1246will also be called when, for example, IPDL detects that the other endpoint has
1247terminated unexpectedly, so it is releasing its reference to the actor, or
1248because an ancestral manager (manager or manager's manager...) received a
1249``__delete__``.  The only way for an actor to avoid ``ActorDestroy`` is for its
1250process to crash first.  ``ActorDestroy`` is always run after its actor is
1251disconnected so it is pointless to try to send messages from it.
1252
1253Why use ``ActorDestroy`` instead of the actor's destructor?  ``ActorDestroy``
1254gives a chance to clean up things that are only used for communication and
1255therefore don't need to live for however long the actor's (reference-counted)
1256object does.  For example, you might have references to shared memory (Shmems)
1257that are no longer valid.  Or perhaps the actor can now release a cache of data
1258that was only needed for processing messages.  It is cleaner to deal with
1259communication-related objects in ``ActorDestroy``, where they become invalid,
1260than to leave them in limbo until the destructor is run.
1261
1262Consider actors to be like normal reference-counted objects, but where IPDL
1263holds a reference while the connection will or does exist.  One common
1264architecture has IPDL holding the `only` reference to an actor.  This is common
1265with actors created by sending construtor messages but the idea is available to
1266any actor.  That only reference is then released when the ``__delete__``
1267message is sent or received.
1268
1269The dual of IPDL holding the only reference is to have client code hold the
1270only reference.  A common pattern to achieve this has been to override the
1271actor's ``AddRef`` to have it send ``__delete__`` only when it's count is down
1272to one reference (which must be IPDL if ``actor.CanSend()`` is true).  A better
1273approach would be to create a reference-counted delegate for your actor that
1274can send ``__delete__`` from its destructor.  IPDL does not guarantee that it
1275will not hold more than one reference to your actor.
1276
1277.. _Top Level Actors:
1278
1279Top Level Actors
1280----------------
1281
1282Recall that top level actors are actors that have no manager.  They are at the
1283root of every actor tree.  There are two settings in which we use top-level
1284actors that differ pretty dramatically.  The first type are top-level actors
1285that are created and maintained in a way that resembles managed actors, but
1286with some important differences we will cover in this section.  The second type
1287of top-level actors are the very first actors in a new process -- these actors
1288are created through different means and closing them (usually) terminates the
1289process.  The `new process example
1290<https://phabricator.services.mozilla.com/D119038>`_ demonstrates both of
1291these.  It is discussed in detail in :ref:`Adding a New Type of Process`.
1292
1293Value of Top Level Actors
1294~~~~~~~~~~~~~~~~~~~~~~~~~
1295
1296Top-level actors are harder to create and destroy than normal actors.  They
1297used to be more heavyweight than managed actors but this has recently been
1298dramatically reduced.
1299
1300.. note::
1301    Top-level actors previously required a dedicated *message channel*, which
1302    are limited OS resources.  This is no longer the case -- message channels
1303    are now shared by actors that connect the same two processes.  This
1304    *message interleaving* can affect message delivery latency but profiling
1305    suggests that the change was basically inconsequential.
1306
1307So why use a new top level actor?
1308
1309* The most dramatic property distinguishing top-level actors is the ability to
1310  *bind* to whatever ``EventTarget`` they choose.  This means that any thread
1311  that runs a ``MessageLoop`` can use the event target for that loop as the
1312  place to send incoming messages.  In other words, ``Recv`` methods would be
1313  run by that message loop, on that thread.  The IPDL apparatus will
1314  asynchronously dispatch messages to these event targets, meaning that
1315  multiple threads can be handling incoming messages at the same time.  The
1316  `PBackground`_ approach was born of a desire to make it easier to exploit
1317  this, although it has some complications, detailed in that section, that
1318  limit its value.
1319* Top level actors suggest modularity.  Actor protocols are tough to debug, as
1320  is just about anything that spans process boundaries.  Modularity can give
1321  other developers a clue as to what they need to know (and what they don't)
1322  when reading an actor's code.  The alternative is proverbial *dumpster
1323  classes* that are as critical to operations (because they do so much) as they
1324  are difficult to learn (because they do so much).
1325* Top level actors are required to connect two processes, regardless of whether
1326  the actors are the first in the process or not.  As said above, the first
1327  actor is created through special means but other actors are created through
1328  messages.  In Gecko, apart from the launcher and main processes, all new
1329  processes X are created with their first actor being between X and the main
1330  process.  To create a connection between X and, say, a content process, the
1331  main process has to send connected ``Endpoints`` to X and to the content
1332  process, which in turn use those endpoints to create new top level actors
1333  that form an actor pair.  This is discussed at length in :ref:`Connecting
1334  With Other Processes`.
1335
1336Top-level actors are not as frictionless as desired but they are probably
1337under-utilized relative to their power.  In cases where it is supported,
1338``PBackground`` is sometimes a simpler alternative to achieve the same goals.
1339
1340Creating Top Level Actors From Other Actors
1341~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1342
1343The most common way to create new top level actors is by creating a pair of
1344connected Endpoints and sending one to the other actor.  This is done exactly
1345the way it sounds.  For example:
1346
1347.. code-block:: c++
1348
1349    bool MyPreexistingActorParent::MakeMyActor() {
1350        Endpoint<PMyActorParent> parentEnd;
1351        Endpoint<PMyActorChild> childEnd;
1352        if (NS_WARN_IF(NS_FAILED(PMyActor::CreateEndpoints(
1353              base::GetCurrentProcId(), OtherPid(), &parentEnd, &childEnd)))) {
1354            // ... handle failure ...
1355            return false;
1356        }
1357        RefPtr<MyActorParent> parent = new MyActorParent;
1358        if (!parentEnd.Bind(parent)) {
1359            // ... handle failure ...
1360            delete parent;
1361            return false;
1362        }
1363        // Do this second so we skip child if parent failed to connect properly.
1364        if (!SendCreateMyActorChild(std::move(childEnd))) {
1365            // ... assume an IPDL error will destroy parent.  Handle failure beyond that ...
1366            return false;
1367        }
1368        return true;
1369    }
1370
1371Here ``MyPreexistingActorParent`` is used to send a child endpoint for the new
1372top level actor to ``MyPreexistingActorChild``, after it hooks up the parent
1373end.  In this example, we bind our new actor to the same thread we are running
1374on -- which must be the same thread ``MyPreexistingActorParent`` is bound to
1375since we are sending ``CreateMyActorChild`` from it.  We could have bound on a
1376different thread.
1377
1378At this point, messages can be sent on the parent.  Eventually, it will start
1379receiving them as well.
1380
1381``MyPreexistingActorChild`` still has to receive the create message.  The code
1382for that handler is pretty similar:
1383
1384.. code-block:: c++
1385
1386    IPCResult MyPreexistingActorChild::RecvCreateMyActorChild(Endpoint<PMyActorChild>&& childEnd) {
1387        RefPtr<MyActorChild> child = new MyActorChild;
1388        if (!childEnd.Bind(child)) {
1389            // ... handle failure and return ok, assuming a related IPDL error will alert the other side to failure ...
1390            return IPC_OK();
1391        }
1392        return IPC_OK();
1393    }
1394
1395Like the parent, the child is ready to send as soon as ``Bind`` is complete.
1396It will start receiving messages soon afterward on the event target for the
1397thread on which it is bound.
1398
1399Creating First Top Level Actors
1400~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1401
1402The first actor in a process is an advanced topic that is covered in
1403:ref:`the documentation for adding a new process<Adding a New Type of Process>`.
1404
1405PBackground
1406-----------
1407
1408Developed as a convenient alternative to top level actors, ``PBackground`` is
1409an IPDL protocol whose managees choose their worker threads in the child
1410process and share a thread dedicated solely to them in the parent process.
1411When an actor (parent or child) should run without hogging the main thread,
1412making that actor a managee of ``PBackground`` (aka a *background actor*) is an
1413option.
1414
1415.. warning::
1416    Background actors can be difficult to use correctly, as spelled out in this
1417    section.  It is recommended that other options -- namely, top-level actors
1418    -- be adopted instead.
1419
1420Background actors can only be used in limited circumstances:
1421
1422* ``PBackground`` only supports the following process connections (where
1423ordering is parent <-> child): main <-> main, main <-> content, main <-> socket
1424and socket <-> content.
1425
1426.. important::
1427
1428    Socket process ``PBackground`` actor support was added after the other
1429    options.  It has some rough edges that aren't easy to anticipate.  In the
1430    future, their support may be broken out into a different actor or removed
1431    altogether.  You are strongly encouraged to use new `Top Level Actors`_
1432    instead of ``PBackground`` actor when communicating with socket process
1433    worker threads.
1434
1435* Background actor creation is always initiated by the child.  Of course, a
1436request to create one can be sent to the child by any other means.
1437* All parent background actors run in the same thread.  This thread is
1438dedicated to serving as the worker for parent background actors.  While it has
1439no other functions, it should remain responsive to all connected background
1440actors.  For this reason, it is a bad idea to conduct long operations in parent
1441background actors.  For such cases, create a top level actor and an independent
1442thread on the parent side instead.
1443* Background actors are currently *not* reference-counted.  IPDL's ownership
1444has to be carefully respected and the (de-)allocators for the new actors have
1445to be defined.  See `The Old Ways`_ for details.
1446
1447A hypothetical layout of ``PBackground`` threads, demonstrating some of the
1448process-type limitations, is shown in the diagram below.
1449
1450.. mermaid::
1451    :align: center
1452    :caption: Hypothetical ``PBackground`` thread setup.  Arrow direction
1453              indicates child-to-parent ``PBackground``-managee relationships.
1454              Parents always share a thread and may be connected to multiple
1455              processes.  Child threads can be any thread, including main.
1456
1457    flowchart LR
1458        subgraph content #1
1459            direction TB
1460            c1tm[main]
1461            c1t1[worker #1]
1462            c1t2[worker #2]
1463            c1t3[worker #3]
1464        end
1465        subgraph content #2
1466            direction TB
1467            c2tm[main]
1468            c2t1[worker #1]
1469            c2t2[worker #2]
1470        end
1471        subgraph socket
1472            direction TB
1473            stm[main]
1474            st1[background parent /\nworker #1]
1475            st2[worker #2]
1476        end
1477        subgraph main
1478            direction TB
1479            mtm[main]
1480            mt1[background parent]
1481        end
1482
1483        %% PBackground connections
1484        c1tm --> mt1
1485        c1t1 --> mt1
1486        c1t2 --> mt1
1487
1488        c1t3 --> mt1
1489        c1t3 --> st1
1490
1491        c2t1 --> st1
1492        c2t1 --> mt1
1493
1494        c2t2 --> mt1
1495
1496        c2tm --> st1
1497
1498        stm --> mt1
1499        st1 --> mt1
1500        st2 --> mt1
1501
1502Creating background actors is done a bit differently than normal managees.  The
1503new managed type and constructor are still added to ``PBackground.ipdl`` as
1504with normal managees but, instead of ``new``-ing the child actor and then
1505passing it in a ``SendFooConstructor`` call, background actors issue the send
1506call to the ``BackgroundChild`` manager, which returns the new child:
1507
1508.. code-block:: c++
1509
1510    // Bind our new PMyBackgroundActorChild to the current thread.
1511    PBackgroundChild* bc = BackgroundChild::GetOrCreateForCurrentThread();
1512    if (!bc) {
1513        return false;
1514    }
1515    PMyBackgroundActorChild* pmyBac = bac->SendMyBackgroundActor(constructorParameters);
1516    if (!pmyBac) {
1517        return false;
1518    }
1519    auto myBac = static_cast<MyBackgroundActorChild*>(pmyBac);
1520
1521.. note::
1522    ``PBackgroundParent`` still needs a ``RecvMyBackgroundActorConstructor``
1523    handler, as usual.  This must be done in the ``ParentImpl`` class.
1524    ``ParentImpl`` is the non-standard name used for the implementation of
1525    ``PBackgroundParent``.
1526
1527To summarize, ``PBackground`` attempts to simplify a common desire in Gecko:
1528to run tasks that communicate between the main and content processes but avoid
1529having much to do with the main thread of either.  Unfortunately, it can be
1530complicated to use correctly and has missed on some favorable IPDL
1531improvements, like reference counting.  While top level actors are always a
1532complete option for independent jobs that need a lot of resources,
1533``PBackground`` offers a compromise for some cases.
1534
1535IPDL Best Practices
1536-------------------
1537
1538IPC performance is affected by a lot of factors.  Many of them are out of our
1539control, like the influence of the system thread scheduler on latency or
1540messages whose travel internally requires multiple legs for security reasons.
1541On the other hand, some things we can and should control for:
1542
1543* Messages incur inherent performance overhead for a number of reasons: IPDL
1544  internal thread latency (e.g. the I/O thread), parameter (de-)serialization,
1545  etc.  While not usually dramatic, this cost can add up.  What's more, each
1546  message generates a fair amound of C++ code.  For these reasons, it is wise
1547  to reduce the number of messages being sent as far as is reasonable.  This
1548  can be as simple as consolidating two asynchronous messages that are always
1549  in succession.  Or it can be more complex, like consolidating two
1550  somewhat-overlapping messages by merging their parameter lists and marking
1551  parameters that may not be needed as optional.  It is easy to go too far down
1552  this path but careful message optimization can show big gains.
1553* Even ``[moveonly]`` parameters are "copied" in the sense that they are
1554  serialized.  The pipes that transmit the data are limited in size and require
1555  allocation.  So understand that the performance of your transmission will be
1556  inversely proportional to the size of your content.  Filter out data you
1557  won't need.  For complex reasons related to Linux pipe write atomicity, it is
1558  highly desirable to keep message sizes below 4K (including a small amount for
1559  message metadata).
1560* On the flip side, very large messages are not permitted by IPDL and will
1561  result in a runtime error.  The limit is currently 256M but message failures
1562  frequently arise even with slightly smaller messages.
1563* Parameters to messages are C++ types and therefore can be very complex in the
1564  sense that they generally represent a tree (or graph) of objects.  If this
1565  tree has a lot of objects in it, and each of them is serialized by
1566  ``ParamTraits``, then we will find that serialization is allocating and
1567  constructing a lot of objects, which will stress the allocator and cause
1568  memory fragmentation.  Avoid this by using larger objects or by sharing this
1569  kind of data through careful use of shared memory.
1570* As it is with everything, concurrency is critical to the performance of IPDL.
1571  For actors, this mostly manifests in the choice of bound thread.  While
1572  adding a managed actor to an existing actor tree may be a quick
1573  implementation, this new actor will be bound to the same thread as the old
1574  one.  This contention may be undesirable.  Other times it may be necessary
1575  since message handlers may need to use data that isn't thread safe or may
1576  need a guarantee that the two actors' messages are received in order.  Plan
1577  up front for your actor hierarchy and its thread model.  Recognize when you
1578  are better off with a new top level actor or ``PBackground`` managee that
1579  facilitates processing messages simultaneously.
1580* Remember that latency will slow your entire thread, including any other
1581  actors/messages on that thread.  If you have messages that will need a long
1582  time to be processed but can run concurrently then they should use actors
1583  that run on a separate thread.
1584* Top-level actors decide a lot of properties for their managees.  Probably the
1585  most important are the process layout of the actor (including which process
1586  is "Parent" and which is "Child") and the thread.  Every top-level actor
1587  should clearly document this, ideally in their .ipdl file.
1588
1589The Old Ways
1590------------
1591
1592TODO:
1593
1594The FUD
1595-------
1596
1597TODO:
1598
1599The Rest
1600--------
1601
1602Nested messages
1603~~~~~~~~~~~~~~~
1604
1605The ``Nested`` message annotations indicate the nesting type of the message.
1606They attempt to process messages in the nested order of the "conversation
1607thread", as found in e.g. a mailing-list client.  This is an advanced concept
1608that should be considered to be discouraged, legacy functionality.
1609Essentially, ``Nested`` messages can make other ``sync`` messages break the
1610policy of blocking their thread -- nested messages are allowed to be received
1611while a sync messagee is waiting for a response.  The rules for when a nested
1612message can be handled are somewhat complex but they try to safely allow a
1613``sync`` message ``M`` to handle and respond to some special (nested) messages
1614that may be needed for the other endpoint to finish processing ``M``.  There is
1615a `comment in MessageChannel`_ with info on how the decision to handle nested
1616messages is made.  For sync nested messages, note that this implies a relay
1617between the endpoints, which could dramatically affect their throughput.
1618
1619Declaring messages to nest requires an annotation on the actor and one on the
1620message itself.  The nesting annotations were listed in `Defining Actors`_ and
1621`Declaring IPDL Messages`_.  We repeat them here.  The actor annotations
1622specify the maximum priority level of messages in the actor.  It is validated
1623by the IPDL compiler.  The annotations are:
1624
1625============================== ================================================
1626``[NestedUpTo=inside_sync]``   Indicates that an actor contains messages of
1627                               priority [Nested=inside_sync] or lower.
1628``[NestedUpTo=inside_cpow]``   Indicates that an actor contains messages of
1629                               priority [Nested=inside_cpow] or lower.
1630============================== ================================================
1631
1632.. note::
1633
1634    The order of the nesting priorities is:
1635    (no nesting priority) < ``inside_sync`` < ``inside_cpow``.
1636
1637The message annotations are:
1638
1639========================== ====================================================
1640``[Nested=inside_sync]``   Indicates that the message can be handled while
1641                           waiting for lower-priority, or in-message-thread,
1642                           sync responses.
1643``[Nested=inside_cpow]``   Indicates that the message can be handled while
1644                           waiting for lower-priority, or in-message-thread,
1645                           sync responses.  Cannot be sent by the parent actor.
1646========================== ====================================================
1647
1648.. note::
1649
1650    ``[Nested=inside_sync]`` messages must be sync (this is enforced by the
1651    IPDL compiler) but ``[Nested=inside_cpow]`` may be async.
1652
1653Nested messages are obviously only interesting when sent to an actor that is
1654performing a synchronous wait.  Therefore, we will assume we are in such a
1655state.  Say ``actorX`` is waiting for a sync reply from ``actorY`` for message
1656``m1`` when ``actorY`` sends ``actorX`` a message ``m2``.  We distinguish two
1657cases here: (1) when ``m2`` is sent while processing ``m1`` (so ``m2`` is sent
1658by the ``RecvM1()`` method -- this is what we mean when we say "nested") and
1659(2) when ``m2`` is unrelated to ``m1``.  Case (2) is easy; ``m2`` is only
1660dispatched while ``m1`` waits if
1661``priority(m2) > priority(m1) > (no priority)`` and the message is being
1662received by the parent, or if ``priority(m2) >= priority(m1) > (no priority)``
1663and the message is being received by the child.  Case (1) is less
1664straightforward.
1665
1666To analyze case (1), we again distinguish the two possible ways we can end up
1667in the nested case: (A) ``m1`` is sent by the parent to the child and ``m2``
1668is sent by the child to the parent, or (B) where the directions are reversed.
1669The following tables explain what happens in all cases:
1670
1671.. |strike| raw:: html
1672
1673   <strike>
1674
1675.. |endstrike| raw:: html
1676
1677   </strike>
1678
1679.. |br| raw:: html
1680
1681   <br/>
1682
1683.. table :: Case (A): Child sends message to a parent that is awaiting a sync response
1684    :align: center
1685
1686    ==============================     ========================      ========================================================
1687    sync ``m1`` type (from parent)     ``m2`` type (from child)      ``m2`` handled or rejected
1688    ==============================     ========================      ========================================================
1689    sync (no priority)                 \*                            IPDL compiler error: parent cannot send sync (no priority)
1690    sync inside_sync                   async (no priority)           |strike| ``m2`` delayed until after ``m1`` completes |endstrike| |br|
1691                                                                     Currently ``m2`` is handled during the sync wait (bug?)
1692    sync inside_sync                   sync (no priority)            |strike| ``m2`` send fails: lower priority than ``m1`` |endstrike| |br|
1693                                                                     Currently ``m2`` is handled during the sync wait (bug?)
1694    sync inside_sync                   sync inside_sync              ``m2`` handled during ``m1`` sync wait: same message thread and same priority
1695    sync inside_sync                   async inside_cpow             ``m2`` handled during ``m1`` sync wait: higher priority
1696    sync inside_sync                   sync inside_cpow              ``m2`` handled during ``m1`` sync wait: higher priority
1697    sync inside_cpow                   \*                            IPDL compiler error: parent cannot use inside_cpow priority
1698    ==============================     ========================      ========================================================
1699
1700.. table :: Case (B): Parent sends message to a child that is awaiting a sync response
1701    :align: center
1702
1703    =============================      =========================      ========================================================
1704    sync ``m1`` type (from child)      ``m2`` type (from parent)      ``m2`` handled or rejected
1705    =============================      =========================      ========================================================
1706    \*                                 async (no priority)            ``m2`` delayed until after ``m1`` completes
1707    \*                                 sync (no priority)             IPDL compiler error: parent cannot send sync (no priority)
1708    sync (no priority)                 sync inside_sync               ``m2`` send fails: no-priority sync messages cannot handle
1709                                                                      incoming messages during wait
1710    sync inside_sync                   sync inside_sync               ``m2`` handled during ``m1`` sync wait: same message thread and same priority
1711    sync inside_cpow                   sync inside_sync               ``m2`` send fails: lower priority than ``m1``
1712    \*                                 async inside_cpow              IPDL compiler error: parent cannot use inside_cpow priority
1713    \*                                 sync inside_cpow               IPDL compiler error: parent cannot use inside_cpow priority
1714    =============================      =========================      ========================================================
1715
1716We haven't seen rule #2 from the `comment in MessageChannel`_ in action but, as
1717the comment mentions, it is needed to break deadlocks in cases where both the
1718parent and child are initiating message-threads simultaneously.  It
1719accomplishes this by favoring the parent's sent messages over the child's when
1720deciding which message-thread to pursue first (and blocks the other until the
1721first completes).  Since this distinction is entirely thread-timing based,
1722client code needs only to be aware that IPDL internals will not deadlock
1723because of this type of race, and that this protection is limited to a single
1724actor tree -- the parent/child messages are only well-ordered when under the
1725same top-level actor so simultaneous sync messages across trees are still
1726capable of deadlock.
1727
1728Clearly, tight control over these types of protocols is required to predict how
1729they will coordinate within themselves and with the rest of the application
1730objects.  Control flow, and hence state, can be very difficult to predict and
1731are just as hard to maintain.  This is one of the key reasons why we have
1732stressed that message priorities should be avoided whenever possible.
1733
1734.. _comment in MessageChannel: https://searchfox.org/mozilla-central/rev/077501b34cca91763ae04f4633a42fddd919fdbd/ipc/glue/MessageChannel.cpp#54-118
1735
1736.. _Message Logging:
1737
1738Message Logging
1739~~~~~~~~~~~~~~~
1740
1741The environment variable ``MOZ_IPC_MESSAGE_LOG`` controls the logging of IPC
1742messages.  It logs details about the transmission and reception of messages.
1743This isn't controlled by ``MOZ_LOG`` -- it is a separate system.  Set this
1744variable to ``1`` to log information on all IPDL messages, or specify a
1745comma-separated list of **top-level** protocols to log (e.g.
1746``MOZ_IPC_MESSAGE_LOG="PMyManagerChild,PMyManagedParent,PMyManagedChild"``).
1747:ref:`Debugging with IPDL Logging` has an example where IPDL logging is useful
1748in tracking down a bug.
1749
1750.. important::
1751    The preceeding ``P`` and the ``Parent`` or ``Child`` suffix are required
1752    when listing individual protocols in ``MOZ_IPC_MESSAGE_LOG``.
1753