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