CINXE.COM
IPDL: Inter-Thread and Inter-Process Message Passing — Firefox Source Docs documentation
<!doctype html> <html class="writer-html5" lang="en" data-content_root="../"> <head> <base href="https://firefox-source-docs.mozilla.org/ipc/ipdl.html"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>IPDL: Inter-Thread and Inter-Process Message Passing — Firefox Source Docs documentation</title> <link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50"> <link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=19f00094"> <link rel="stylesheet" type="text/css" href="../_static/graphviz.css?v=fd3f3429"> <link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b"> <link rel="stylesheet" type="text/css" href="../_static/custom_theme.css?v=a7d3e023"> <link rel="stylesheet" type="text/css" href="../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css?v=0a3b3ea7"> <link rel="shortcut icon" href="../_static/firefox.ico"><!--[if lt IE 9]> <script src="../_static/js/html5shiv.min.js"></script> <![endif]--> <script src="../_static/jquery.js?v=5d32c60e"></script> <script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script> <script src="../_static/documentation_options.js?v=5929fcd5"></script> <script src="../_static/doctools.js?v=9a2dae69"></script> <script src="../_static/sphinx_highlight.js?v=dc90522c"></script> <script src="../_static/clipboard.min.js?v=a7894cd8"></script> <script src="../_static/copybutton.js?v=30646c52"></script> <script src="../_static/design-tabs.js?v=36754332"></script> <script type="module" src="https://cdn.jsdelivr.net/npm/mermaid@11.2.0/dist/mermaid.esm.min.mjs"></script> <script type="module" src="https://cdn.jsdelivr.net/npm/@mermaid-js/layout-elk@0.1.4/dist/mermaid-layout-elk.esm.min.mjs"></script> <script type="module">import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@11.2.0/dist/mermaid.esm.min.mjs";import elkLayouts from "https://cdn.jsdelivr.net/npm/@mermaid-js/layout-elk@0.1.4/dist/mermaid-layout-elk.esm.min.mjs";mermaid.registerLayoutLoaders(elkLayouts);mermaid.initialize({startOnLoad:false});</script> <script src="https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js"></script> <script type="module"> import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@11.2.0/dist/mermaid.esm.min.mjs"; window.addEventListener("load", () => mermaid.run()); </script> <script src="../_static/js/theme.js"></script> <link rel="index" title="Index" href="../genindex.html"> <link rel="search" title="Search" href="../search.html"> <link rel="next" title="Gecko Processes" href="processes.html"> <link rel="prev" title="Processes, Threads and IPC" href="index.html"> <meta http-equiv="X-Translated-By" content="Google"> <meta http-equiv="X-Translated-To" content="iw"> <script type="text/javascript" src="https://www.gstatic.com/_/translate_http/_/js/k=translate_http.tr.en_GB.1hbgkFx4Qn8.O/am=DgY/d=1/rs=AN8SPfqlmAPxwfG457BPbRXwNq39oSMGHg/m=corsproxy" data-sourceurl="https://firefox-source-docs.mozilla.org/ipc/ipdl.html"></script> <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" rel="stylesheet"> <script type="text/javascript" src="https://www.gstatic.com/_/translate_http/_/js/k=translate_http.tr.en_GB.1hbgkFx4Qn8.O/am=DgY/d=1/exm=corsproxy/ed=1/rs=AN8SPfqlmAPxwfG457BPbRXwNq39oSMGHg/m=phishing_protection" data-phishing-protection-enabled="false" data-forms-warning-enabled="true" data-source-url="https://firefox-source-docs.mozilla.org/ipc/ipdl.html"></script> <meta name="robots" content="none"> </head> <body class="wy-body-for-nav"> <script type="text/javascript" src="https://www.gstatic.com/_/translate_http/_/js/k=translate_http.tr.en_GB.1hbgkFx4Qn8.O/am=DgY/d=1/exm=corsproxy,phishing_protection/ed=1/rs=AN8SPfqlmAPxwfG457BPbRXwNq39oSMGHg/m=navigationui" data-environment="prod" data-proxy-url="https://firefox--source--docs-mozilla-org.translate.goog" data-proxy-full-url="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB" data-source-url="https://firefox-source-docs.mozilla.org/ipc/ipdl.html" data-source-language="pl" data-target-language="iw" data-display-language="en-GB" data-detected-source-language="" data-is-source-untranslated="false" data-source-untranslated-url="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://firefox-source-docs.mozilla.org/ipc/ipdl.html&anno=2" data-client="tr"></script> <div class="wy-grid-for-nav"> <nav data-toggle="wy-nav-shift" class="wy-nav-side"> <div class="wy-side-scroll"> <div class="wy-side-nav-search"><a href="https://firefox--source--docs-mozilla-org.translate.goog/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB" class="icon icon-home"> Firefox Source Docs <img src="../_static/firefox-wordmark.svg" class="logo" alt="Logo"> </a><!-- -- This code is governed by the BSD license ----> <div> <h3>Quick search</h3> <script> (function () { var cx = "dd12886298f75dbef"; var gcse = document.createElement("script"); gcse.async = true; gcse.src = "https://cse.google.com/cse.js?cx=" + cx; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(gcse, s); })(); </script><gcse:search></gcse:search> </div> </div> <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu"> <p class="caption" role="heading"><span class="caption-text">Overview</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/glossary/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">A Glossary of Common Terms</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/overview/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">A Quick Guide to Mozilla Applications</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Getting Started</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/setup/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Getting Set Up To Work On The Firefox Codebase</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Working On Firefox</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/contributing/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Working on Firefox</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/bug-mgmt/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Bug Handling</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Firefox User Guide</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/devtools-user/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Firefox DevTools User Docs</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Source Code Documentation</span></p> <ul class="current"> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mots/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Governance</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/browser/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Firefox Front-end</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/dom/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">DOM</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/editor/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Editor</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/layout/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Style system (CSS) & Layout</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/gfx/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Graphics</a></li> <li class="toctree-l1 current"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Processes, Threads and IPC</a> <ul class="current"> <li class="toctree-l2 current"><a class="current reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#">IPDL: Inter-Thread and Inter-Process Message Passing</a> <ul> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-idea">The Idea</a></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-approach">The Approach</a> <ul> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-steps-to-making-a-new-actor">The Steps To Making A New Actor</a></li> </ul></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-protocol-language">The Protocol Language</a> <ul> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#using-the-ipdl-compiler">Using The IPDL compiler</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#referencing-externally-defined-data-types-ipdl-includes">Referencing Externally Defined Data Types: IPDL Includes</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#namespaces">Namespaces</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#generating-ipdl-aware-c-data-types-ipdl-structs-and-unions">Generating IPDL-Aware C++ Data Types: IPDL Structs and Unions</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#defining-actors">Defining Actors</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#declaring-ipdl-messages">Declaring IPDL Messages</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#ipdl-syntax-quick-reference">IPDL Syntax Quick Reference</a></li> </ul></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-c-interface">The C++ Interface</a> <ul> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#paramtraits">ParamTraits</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#ipdl-structs-and-unions-in-c">IPDL Structs and Unions in C++</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actors-and-messages-in-c">Actors and Messages in C++</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actor-lifetimes-in-c">Actor Lifetimes in C++</a></li> </ul></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#top-level-actors">Top Level Actors</a> <ul> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#value-of-top-level-actors">Value of Top Level Actors</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#creating-top-level-actors-from-other-actors">Creating Top Level Actors From Other Actors</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#creating-first-top-level-actors">Creating First Top Level Actors</a></li> </ul></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#pbackground">PBackground</a></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#ipdl-best-practices">IPDL Best Practices</a></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-old-ways">The Old Ways</a></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-fud">The FUD</a></li> <li class="toctree-l3"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-rest">The Rest</a> <ul> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#nested-messages">Nested messages</a></li> <li class="toctree-l4"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#message-logging">Message Logging</a></li> </ul></li> </ul></li> <li class="toctree-l2"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/processes.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Gecko Processes</a></li> <li class="toctree-l2"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/utility_process.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Utility Process</a></li> </ul></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/devtools/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Firefox DevTools Contributor Docs</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/toolkit/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Toolkit</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/js/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">SpiderMonkey</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mobile/android/geckoview/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">GeckoView</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mobile/android/fenix/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Fenix</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mobile/android/focus-android/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Focus for Android</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/dom/bindings/webidl/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">WebIDL</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/modules/libpref/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">libpref</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/networking/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Networking</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/remote/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Remote Protocols</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/services/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Services</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/uriloader/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">File Handling</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/widget/cocoa/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Firefox on macOS</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/widget/windows/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Firefox on Windows</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/toolkit/components/ml/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Firefox AI Platform</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/accessible/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Accessibility</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/code-quality/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Code quality</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/writing-rust-code/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Writing Rust Code</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/rust-components/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Rust Components</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/profiler/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Gecko Profiler</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/performance/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Performance</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/storage/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Database bindings (SQLite, KV, …)</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/xpcom/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">XPCOM</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/nspr/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">NSPR</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/security/nss/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Network Security Services (NSS)</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/content-security/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Web Security Checks in Gecko</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">The Firefox Build System</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mach/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Mach</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/try/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Pushing to Try</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/build/buildsystem/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Build System</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/taskcluster/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Firefox CI and Taskgraph</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/moztreedocs/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Managing Documentation</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mozbuild/vendor/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Vendoring Third Party Components</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Testing & Test Infrastructure</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/automated-testing/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Automated Testing</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/treeherder-try/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Understanding Treeherder Results</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/sheriffed-intermittents/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Sheriffed intermittent failures</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/tests-for-new-config/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Turning on Firefox tests for a new configuration</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/intermittent/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Avoiding intermittent tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/testing-policy/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Testing Policy</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/ci-configs/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Configuration Changes</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/browser-chrome/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Browser chrome mochitests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/chrome-tests/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Chrome Tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/marionette/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Marionette</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/geckodriver/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">geckodriver</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/test-verification/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Test Verification</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/webrender/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">WebRender Tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/mochitest-plain/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Mochitest</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/xpcshell/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">XPCShell tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/tps/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">TPS</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/web-platform/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">web-platform-tests</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/gtest/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">GTest</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/fuzzing/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Fuzzing</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/sanitizer/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Sanitizer</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing/perfdocs/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Performance Testing</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/tools/code-coverage/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Code coverage</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/testing-rust-code/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Testing & Debugging Rust Code</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Releases & Updates</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/update-infrastructure/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Mozilla Update Infrastructure</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/update-infrastructure/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#watershed-updates">Watershed Updates</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/update-infrastructure/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#desupport-updates">Desupport Updates</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Localization & Internationalization</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/intl/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Internationalization</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/l10n/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Localization</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Firefox and Python</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/mozbase/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">mozbase</a></li> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/python/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Using third-party Python packages</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Metrics Collected in Firefox</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/metrics/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Metrics</a></li> </ul> </div> </div> </nav> <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"> <nav class="wy-nav-top" aria-label="Mobile navigation menu"><i data-toggle="wy-nav-top" class="fa fa-bars"></i> <a href="https://firefox--source--docs-mozilla-org.translate.goog/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Firefox Source Docs</a> </nav> <div class="wy-nav-content"> <div class="rst-content"><!-- This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this file, - You can obtain one at http://mozilla.org/MPL/2.0/. --> <div role="navigation" aria-label="Page navigation"> <ul class="wy-breadcrumbs"> <li><a href="https://firefox--source--docs-mozilla-org.translate.goog/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB" class="icon icon-home" aria-label="Home"></a></li> <li class="breadcrumb-item"><a href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB">Processes, Threads and IPC</a></li> <li class="breadcrumb-item active">IPDL: Inter-Thread and Inter-Process Message Passing</li> <li class="wy-breadcrumbs-aside"><a href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://bugzilla.mozilla.org/enter_bug.cgi?product%3DDeveloper%2BInfrastructure%26component%3DFirefox%2BSource%2BDocs%253A%2BContent%26short_desc%3DDocumentation%2Bissue%2Bon%2Bipc/ipdl%26comment%3DURL%2B%3D%2Bhttps://firefox-source-docs.mozilla.org/ipc/ipdl.html%26bug_file_loc%3Dhttps://firefox-source-docs.mozilla.org/ipc/ipdl.html" rel="nofollow">Report an issue</a> / <a href="https://firefox--source--docs-mozilla-org.translate.goog/_sources/ipc/ipdl.rst.txt?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB" rel="nofollow"> View page source</a></li> </ul> <hr> </div> <div role="main" class="document" itemscope itemtype="http://schema.org/Article"> <div itemprop="articleBody"> <section id="ipdl-inter-thread-and-inter-process-message-passing"> <h1>IPDL: Inter-Thread and Inter-Process Message Passing<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#ipdl-inter-thread-and-inter-process-message-passing" title="Link to this heading">¶</a></h1> <section id="the-idea"> <h2>The Idea<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-idea" title="Link to this heading">¶</a></h2> <p><strong>IPDL</strong>, the “Inter-[thread|process] Protocol Definition Language”, is the Mozilla-specific language that allows code to communicate between system threads or processes in a standardized, efficient, safe, secure and platform-agnostic way. IPDL communications take place between <em>parent</em> and <em>child</em> objects called <em>actors</em>. The architecture is inspired by the <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://en.wikipedia.org/wiki/Actor_model">actor model</a>.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>IPDL actors differ from the actor model in one significant way – all IPDL communications are <em>only</em> between a parent and its only child.</p> </div> <p>The actors that constitute a parent/child pair are called <strong>peers</strong>. Peer actors communicate through an <strong>endpoint</strong>, which is an end of a message pipe. An actor is explicitly bound to its endpoint, which in turn is bound to a particular thread soon after it is constructed. An actor never changes its endpoint and may only send and receive predeclared <strong>messages</strong> from/to that endpoint, on that thread. Violations result in runtime errors. A thread may be bound to many otherwise unrelated actors but an endpoint supports <strong>top-level</strong> actors and any actors they <strong>manage</strong> (see below).</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>More precisely, endpoints can be bound to any <code class="docutils literal notranslate"><span class="pre">nsISerialEventTarget</span></code>, which are themselves associated with a specific thread. By default, IPDL will bind to the current thread’s “main” serial event target, which, if it exists, is retrieved with <code class="docutils literal notranslate"><span class="pre">GetCurrentSerialEventTarget</span></code>. For the sake of clarity, this document will frequently refer to actors as bound to threads, although the more precise interpretation of serial event targets is also always valid.</p> </div> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Internally, we use the “Ports” component of the <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://chromium.googlesource.com/chromium/src/%2B/refs/heads/main/mojo/core/README.md%23Port">Chromium Mojo</a> library to <em>multiplex</em> multiple endpoints (and, therefore, multiple top-level actors). This means that the endpoints communicate over the same native pipe, which conserves limited OS resources. The implications of this are discussed in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#ipdl-best-practices">IPDL Best Practices</a>.</p> </div> <p>Parent and child actors may be bound to threads in different processes, in different threads in the same process, or even in the same thread in the same process. That last option may seem unreasonable but actors are versatile and their layout can be established at run-time so this could theoretically arise as the result of run-time choices. One large example of this versatility is <code class="docutils literal notranslate"><span class="pre">PCompositorBridge</span></code> actors, which in different cases connect endpoints in the main process and the GPU process (for UI rendering on Windows), in a content process and the GPU process (for content rendering on Windows), in the main process and the content process (for content rendering on Mac, where there is no GPU process), or between threads on the main process (UI rendering on Mac). For the most part, this does not require elaborate or redundant coding; it just needs endpoints to be bound judiciously at runtime. The example in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/processes.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#connecting-with-other-processes"><span class="std std-ref">Connecting With Other Processes</span></a> shows one way this can be done. It also shows that, without proper plain-language documentation of <em>all</em> of the ways endpoints are configured, this can quickly lead to unmaintainable code. Be sure to document your endpoint bindings thoroughly!!!</p> </section> <section id="the-approach"> <h2>The Approach<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-approach" title="Link to this heading">¶</a></h2> <p>The actor framework will schedule tasks to run on its associated event target, in response to messages it receives. Messages are specified in an IPDL <strong>protocol</strong> file and the response handler tasks are defined per-message by C++ methods. As actors only communicate in pairs, and each is bound to one thread, sending is always done sequentially, never concurrently (same for receiving). This means that it can, and does, guarantee that an actor will always receive messages in the same order they were sent by its related actor – and that this order is well defined since the related actor can only send from one thread.</p> <div class="admonition warning"> <p class="admonition-title">Warning</p> <p>There are a few (rare) exceptions to the message order guarantee. They include <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-rest">synchronous nested</a> messages and messages with a <code class="docutils literal notranslate"><span class="pre">[Priority]</span></code> or <code class="docutils literal notranslate"><span class="pre">[Compress]</span></code> annotation.</p> </div> <p>An IPDL protocol file specifies the messages that may be sent between parent and child actors, as well as the direction and payload of those messages. Messages look like function calls but, from the standpoint of their caller, they may start and end at any time in the future – they are <em>asynchronous</em>, so they won’t block their sending actors or any other components that may be running in the actor’s thread’s <code class="docutils literal notranslate"><span class="pre">MessageLoop</span></code>.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Not all IPDL messages are asynchronous. Again, we run into exceptions for messages that are synchronous or <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-rest">synchronous nested</a>. Use of synchronous and nested messages is strongly discouraged but may not always be avoidable. They will be defined later, along with superior alternatives to both that should work in nearly all cases.</p> </div> <p>Protocol files are compiled by the <em>IPDL compiler</em> in an early stage of the build process. The compiler generates C++ code that reflects the protocol. Specifically, it creates one C++ class that represents the parent actor and one that represents the child. The generated files are then automatically included in the C++ build process. The generated classes contain public methods for sending the protocol messages, which client code will use as the entry-point to IPC communication. The generated methods are built atop our IPC framework, defined in <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/source/ipc">/ipc</a>, that standardizes the safe and secure use of sockets, pipes, shared memory, etc on all supported platforms. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#using-the-ipdl-compiler">Using The IPDL compiler</a> for more on integration with the build process.</p> <p>Client code must be written that subclasses these generated classes, in order to add handlers for the tasks generated to respond to each message. It must also add routines (<code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code>) that define serialization and deserialization for any types used in the payload of a message that aren’t already known to the IPDL system. Primitive types, and a bunch of Mozilla types, have predefined <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> (<a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/source/ipc/glue/IPCMessageUtils.h">here</a> and <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/source/ipc/glue/IPCMessageUtilsSpecializations.h">here</a>).</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Among other things, client code that uses the generated code must include <code class="docutils literal notranslate"><span class="pre">chromium-config.mozbuild</span></code> in its <code class="docutils literal notranslate"><span class="pre">moz.build</span></code> file. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#using-the-ipdl-compiler">Using The IPDL compiler</a> for a complete list of required build changes.</p> </div> <section id="the-steps-to-making-a-new-actor"> <h3>The Steps To Making A New Actor<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-steps-to-making-a-new-actor" title="Link to this heading">¶</a></h3> <ol class="arabic"> <li><p>Decide what folder you will work in and create:</p> <blockquote> <div> <ol class="arabic simple"> <li><p>An IPDL protocol file, named for your actor (e.g. <code class="docutils literal notranslate"><span class="pre">PMyActor.ipdl</span></code> – actor protocols must begin with a <code class="docutils literal notranslate"><span class="pre">P</span></code>). See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-protocol-language">The Protocol Language</a>.</p></li> <li><p>Properly-named source files for your actor’s parent and child implementations (e.g. <code class="docutils literal notranslate"><span class="pre">MyActorParent.h</span></code>, <code class="docutils literal notranslate"><span class="pre">MyActorChild.h</span></code> and, optionally, adjacent .cpp files). See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-c-interface">The C++ Interface</a>.</p></li> <li><p>IPDL-specific updates to the <code class="docutils literal notranslate"><span class="pre">moz.build</span></code> file. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#using-the-ipdl-compiler">Using The IPDL compiler</a>.</p></li> </ol> </div> </blockquote></li> <li><p>Write your actor protocol (.ipdl) file:</p> <blockquote> <div> <ol class="arabic simple"> <li><p>Decide whether you need a top-level actor or a managed actor. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#top-level-actors">Top Level Actors</a>.</p></li> <li><p>Find/write the IPDL and C++ data types you will use in communication. Write <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> for C++ data types that don’t have them. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#generating-ipdl-aware-c-data-types-ipdl-structs-and-unions">Generating IPDL-Aware C++ Data Types: IPDL Structs and Unions</a> for IPDL structures. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#referencing-externally-defined-data-types-ipdl-includes">Referencing Externally Defined Data Types: IPDL Includes</a> and <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#paramtraits">ParamTraits</a> for C++ data types.</p></li> <li><p>Write your actor and its messages. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#defining-actors">Defining Actors</a>.</p></li> </ol> </div> </blockquote></li> <li><p>Write C++ code to create and destroy instances of your actor at runtime.</p> <blockquote> <div> <ul class="simple"> <li><p>For managed actors, see <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actor-lifetimes-in-c">Actor Lifetimes in C++</a>.</p></li> <li><p>For top-level actors, see <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#creating-top-level-actors-from-other-actors">Creating Top Level Actors From Other Actors</a>. The first actor in a process is a very special exception – see <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#creating-first-top-level-actors">Creating First Top Level Actors</a>.</p></li> </ul> </div> </blockquote></li> <li><p>Write handlers for your actor’s messages. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actors-and-messages-in-c">Actors and Messages in C++</a>.</p></li> <li><p>Start sending messages through your actors! Again, see <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actors-and-messages-in-c">Actors and Messages in C++</a>.</p></li> </ol> </section> </section> <section id="the-protocol-language"> <h2>The Protocol Language<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-protocol-language" title="Link to this heading">¶</a></h2> <p>This document will follow the integration of two actors into Firefox – <code class="docutils literal notranslate"><span class="pre">PMyManager</span></code> and <code class="docutils literal notranslate"><span class="pre">PMyManaged</span></code>. <code class="docutils literal notranslate"><span class="pre">PMyManager</span></code> will manage <code class="docutils literal notranslate"><span class="pre">PMyManaged</span></code>. A good place to start is with the IPDL actor definitions. These are files that are named for the actor (e.g. <code class="docutils literal notranslate"><span class="pre">PMyManager.ipdl</span></code>) and that declare the messages that a protocol understands. These actors are for demonstration purposes and involve quite a bit of functionality. Most actors will use a very small fraction of these features.</p> <div class="highlight-c++ notranslate" id="pmymanager-ipdl"> <div class="highlight"> <pre><span></span><span class="n">include</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManaged</span><span class="p">;</span> <span class="n">include</span><span class="w"> </span><span class="n">MyTypes</span><span class="p">;</span><span class="w"> </span><span class="c1">// for MyActorPair</span> <span class="k">using</span><span class="w"> </span><span class="n">MyActorEnum</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/myns/MyActorUtils.h"</span><span class="p">;</span> <span class="k">using</span><span class="w"> </span><span class="n">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyData</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/MyDataTypes.h"</span><span class="p">;</span> <span class="p">[</span><span class="n">MoveOnly</span><span class="p">]</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyOtherData</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/MyDataTypes.h"</span><span class="p">;</span> <span class="p">[</span><span class="n">RefCounted</span><span class="p">]</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyThirdData</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/MyDataTypes.h"</span><span class="p">;</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">mozilla</span><span class="w"> </span><span class="p">{</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">myns</span><span class="w"> </span><span class="p">{</span> <span class="p">[</span><span class="n">Comparable</span><span class="p">]</span><span class="w"> </span><span class="k">union</span><span class="w"> </span><span class="nc">MyUnion</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="kt">float</span><span class="p">;</span><span class="w"> </span> <span class="w"> </span><span class="n">MyOtherData</span><span class="p">;</span> <span class="p">};</span> <span class="p">[</span><span class="n">ChildProc</span><span class="o">=</span><span class="n">any</span><span class="p">]</span> <span class="n">sync</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManager</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">manages</span><span class="w"> </span><span class="n">PMyManaged</span><span class="p">;</span> <span class="w"> </span><span class="nl">parent</span><span class="p">:</span> <span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="nf">__delete__</span><span class="p">(</span><span class="n">nsString</span><span class="w"> </span><span class="n">aNote</span><span class="p">);</span> <span class="w"> </span><span class="n">sync</span><span class="w"> </span><span class="nf">SomeMsg</span><span class="p">(</span><span class="n">MyActorPair</span><span class="o">?</span><span class="w"> </span><span class="n">aActors</span><span class="p">,</span><span class="w"> </span><span class="n">MyData</span><span class="p">[]</span><span class="w"> </span><span class="n">aMyData</span><span class="p">)</span> <span class="w"> </span><span class="n">returns</span><span class="w"> </span><span class="p">(</span><span class="kt">int32_t</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="w"> </span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">MyUnion</span><span class="w"> </span><span class="n">aUnion</span><span class="p">);</span> <span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="nf">PMyManaged</span><span class="p">();</span> <span class="w"> </span><span class="nl">both</span><span class="p">:</span> <span class="w"> </span><span class="p">[</span><span class="n">Tainted</span><span class="p">]</span><span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="n">AnotherMsg</span><span class="p">(</span><span class="n">MyActorEnum</span><span class="w"> </span><span class="n">aEnum</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="w"> </span><span class="n">aNumber</span><span class="p">)</span> <span class="w"> </span><span class="n">returns</span><span class="w"> </span><span class="p">(</span><span class="n">MyOtherData</span><span class="w"> </span><span class="n">aOtherData</span><span class="p">);</span> <span class="p">};</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace myns</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace mozilla</span> </pre> </div> </div> <div class="highlight-c++ notranslate" id="pmymanaged-ipdl"> <div class="highlight"> <pre><span></span><span class="n">include</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManager</span><span class="p">;</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">mozilla</span><span class="w"> </span><span class="p">{</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">myns</span><span class="w"> </span><span class="p">{</span> <span class="n">protocol</span><span class="w"> </span><span class="n">PMyManaged</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">manager</span><span class="w"> </span><span class="n">PMyManager</span><span class="p">;</span> <span class="w"> </span><span class="nl">child</span><span class="p">:</span> <span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="nf">__delete__</span><span class="p">(</span><span class="n">Shmem</span><span class="w"> </span><span class="n">aShmem</span><span class="p">);</span> <span class="p">};</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace myns</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace mozilla</span> </pre> </div> </div> <p>These files reference three additional files. <code class="docutils literal notranslate"><span class="pre">MyTypes.ipdlh</span></code> is an “IPDL header” that can be included into <code class="docutils literal notranslate"><span class="pre">.ipdl</span></code> files as if it were inline, except that it also needs to include any external actors and data types it uses:</p> <div class="highlight-c++ notranslate" id="mytypes-ipdlh"> <div class="highlight"> <pre><span></span><span class="n">include</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManaged</span><span class="p">;</span> <span class="k">struct</span><span class="w"> </span><span class="nc">MyActorPair</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">PMyManaged</span><span class="w"> </span><span class="n">actor1</span><span class="p">;</span> <span class="w"> </span><span class="n">nullable</span><span class="w"> </span><span class="n">PMyManaged</span><span class="w"> </span><span class="n">actor2</span><span class="p">;</span> <span class="p">};</span> </pre> </div> </div> <p><code class="docutils literal notranslate"><span class="pre">MyActorUtils.h</span></code> and <code class="docutils literal notranslate"><span class="pre">MyDataTypes.h</span></code> are normal C++ header files that contain definitions for types passed by these messages, as well as instructions for serializing them. They will be covered in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-c-interface">The C++ Interface</a>.</p> <section id="using-the-ipdl-compiler"> <h3>Using The IPDL compiler<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#using-the-ipdl-compiler" title="Link to this heading">¶</a></h3> <p>To build IPDL files, list them (alphabetically sorted) in a <code class="docutils literal notranslate"><span class="pre">moz.build</span></code> file. In this example, the <code class="docutils literal notranslate"><span class="pre">.ipdl</span></code> and <code class="docutils literal notranslate"><span class="pre">.ipdlh</span></code> files would be alongside a <code class="docutils literal notranslate"><span class="pre">moz.build</span></code> containing:</p> <div class="highlight-python notranslate"> <div class="highlight"> <pre><span></span><span class="n">IPDL_SOURCES</span> <span class="o">+=</span> <span class="p">[</span> <span class="s2">"MyTypes.ipdlh"</span><span class="p">,</span> <span class="s2">"PMyManaged.ipdl"</span><span class="p">,</span> <span class="s2">"PMyManager.ipdl"</span><span class="p">,</span> <span class="p">]</span> <span class="n">UNIFIED_SOURCES</span> <span class="o">+=</span> <span class="p">[</span> <span class="s2">"MyManagedChild.cpp"</span><span class="p">,</span> <span class="s2">"MyManagedParent.cpp"</span><span class="p">,</span> <span class="s2">"MyManagerChild.cpp"</span><span class="p">,</span> <span class="s2">"MyManagerParent.cpp"</span><span class="p">,</span> <span class="p">]</span> <span class="n">include</span><span class="p">(</span><span class="s2">"/ipc/chromium/chromium-config.mozbuild"</span><span class="p">)</span> </pre> </div> </div> <p><code class="docutils literal notranslate"><span class="pre">chromium-config.mozbuild</span></code> sets up paths so that generated IPDL header files are in the proper scope. If it isn’t included, the build will fail with <code class="docutils literal notranslate"><span class="pre">#include</span></code> errors in both your actor code and some internal ipc headers. For example:</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span><span class="n">c</span><span class="p">:</span><span class="o">/</span><span class="n">mozilla</span><span class="o">-</span><span class="n">src</span><span class="o">/</span><span class="n">mozilla</span><span class="o">-</span><span class="n">unified</span><span class="o">/</span><span class="n">obj</span><span class="o">-</span><span class="mi">64</span><span class="o">/</span><span class="n">dist</span><span class="o">/</span><span class="n">include</span>\<span class="n">ipc</span><span class="o">/</span><span class="n">IPCMessageUtils</span><span class="o">.</span><span class="n">h</span><span class="p">(</span><span class="mi">13</span><span class="p">,</span><span class="mi">10</span><span class="p">):</span> <span class="n">fatal</span> <span class="n">error</span><span class="p">:</span> <span class="s1">'build/build_config.h'</span> <span class="n">file</span> <span class="ow">not</span> <span class="n">found</span> </pre> </div> </div> <p><code class="docutils literal notranslate"><span class="pre">.ipdl</span></code> files are compiled to C++ files as one of the earliest post-configure build steps. Those files are, in turn, referenced throughout the source code and build process. From <code class="docutils literal notranslate"><span class="pre">PMyManager.ipdl</span></code> the compiler generates two header files added to the build context and exported globally: <code class="docutils literal notranslate"><span class="pre">mozilla/myns/PMyManagerParent.h</span></code> and <code class="docutils literal notranslate"><span class="pre">mozilla/myns/PMyManagerChild.h</span></code>, as discussed in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#namespaces">Namespaces</a> below. These files contain the base classes for the actors. It also makes several other files, including C++ source files and another header, that are automatically included into the build and should not require attention.</p> <p>C++ definions of the actors are required for IPDL. They define the actions that are taken in response to messages – without this, they would have no value. There will be much more on this when we discuss <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actors-and-messages-in-c">Actors and Messages in C++</a> but note here that C++ header files named for the actor are required by the IPDL <cite>compiler</cite>. The example would expect <code class="docutils literal notranslate"><span class="pre">mozilla/myns/MyManagedChild.h</span></code>, <code class="docutils literal notranslate"><span class="pre">mozilla/myns/MyManagedParent.h</span></code>, <code class="docutils literal notranslate"><span class="pre">mozilla/myns/MyManagerChild.h</span></code> and <code class="docutils literal notranslate"><span class="pre">mozilla/myns/MyManagerParent.h</span></code> and will not build without them.</p> </section> <section id="referencing-externally-defined-data-types-ipdl-includes"> <h3>Referencing Externally Defined Data Types: IPDL Includes<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#referencing-externally-defined-data-types-ipdl-includes" title="Link to this heading">¶</a></h3> <p>Let’s begin with <code class="docutils literal notranslate"><span class="pre">PMyManager.ipdl</span></code>. It starts by including types that it will need from other places:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="n">include</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManaged</span><span class="p">;</span> <span class="n">include</span><span class="w"> </span><span class="n">MyTypes</span><span class="p">;</span><span class="w"> </span><span class="c1">// for MyActorPair</span> <span class="k">using</span><span class="w"> </span><span class="n">MyActorEnum</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/myns/MyActorUtils.h"</span><span class="p">;</span> <span class="k">using</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyData</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/MyDataTypes.h"</span><span class="p">;</span> <span class="p">[</span><span class="n">MoveOnly</span><span class="p">]</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="n">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyOtherData</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/MyDataTypes.h"</span><span class="p">;</span> <span class="p">[</span><span class="n">RefCounted</span><span class="p">]</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyThirdData</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/MyDataTypes.h"</span><span class="p">;</span> </pre> </div> </div> <p>The first line includes a protocol that PMyManager will manage. That protocol is defined in its own <code class="docutils literal notranslate"><span class="pre">.ipdl</span></code> file. Cyclic references are expected and pose no concern.</p> <p>The second line includes the file <code class="docutils literal notranslate"><span class="pre">MyTypes.ipdlh</span></code>, which defines types like structs and unions, but in IPDL, which means they have behavior that goes beyond the similar C++ concepts. Details can be found in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#generating-ipdl-aware-c-data-types-ipdl-structs-and-unions">Generating IPDL-Aware C++ Data Types: IPDL Structs and Unions</a>.</p> <p>The final lines include types from C++ headers. Additionally, the [RefCounted] and [MoveOnly] attributes tell IPDL that the types have special functionality that is important to operations. These are the data type attributes currently understood by IPDL:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[RefCounted]</span></code></p></td> <td><p>Type <code class="docutils literal notranslate"><span class="pre">T</span></code> is reference counted (by <code class="docutils literal notranslate"><span class="pre">AddRef</span></code>/<code class="docutils literal notranslate"><span class="pre">Release</span></code>). As a parameter to a message or as a type in IPDL structs/unions, it is referenced as a <code class="docutils literal notranslate"><span class="pre">RefPtr<T></span></code>.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[MoveOnly]</span></code></p></td> <td><p>The type <code class="docutils literal notranslate"><span class="pre">T</span></code> is treated as uncopyable. When used as a parameter in a message or an IPDL struct/union, it is as an r-value <code class="docutils literal notranslate"><span class="pre">T&&</span></code>.</p></td> </tr> </tbody> </table> <p>Finally, note that <code class="docutils literal notranslate"><span class="pre">using</span></code>, <code class="docutils literal notranslate"><span class="pre">using</span> <span class="pre">class</span></code> and <code class="docutils literal notranslate"><span class="pre">using</span> <span class="pre">struct</span></code> are all valid syntax. The <code class="docutils literal notranslate"><span class="pre">class</span></code> and <code class="docutils literal notranslate"><span class="pre">struct</span></code> keywords are optional.</p> </section> <section id="namespaces"> <h3>Namespaces<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#namespaces" title="Link to this heading">¶</a></h3> <p>From the IPDL file:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="k">namespace</span><span class="w"> </span><span class="nn">mozilla</span><span class="w"> </span><span class="p">{</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">myns</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// ... data type and actor definitions ...</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace myns</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace mozilla</span> </pre> </div> </div> <p>Namespaces work similar to the way they do in C++. They also mimic the notation, in an attempt to make them comfortable to use. When IPDL actors are compiled into C++ actors, the namespace scoping is carried over. As previously noted, when C++ types are included into IPDL files, the same is true. The most important way in which they differ is that IPDL also uses the namespace to establish the path to the generated files. So, the example defines the IPDL data type <code class="docutils literal notranslate"><span class="pre">mozilla::myns::MyUnion</span></code> and the actors <code class="docutils literal notranslate"><span class="pre">mozilla::myns::PMyManagerParent</span></code> and <code class="docutils literal notranslate"><span class="pre">mozilla::myns::PMyManagerChild</span></code>, which can be included from <code class="docutils literal notranslate"><span class="pre">mozilla/myns/PMyManagerParent.h</span></code>, <code class="docutils literal notranslate"><span class="pre">mozilla/myns/PMyManagerParent.h</span></code> and <code class="docutils literal notranslate"><span class="pre">mozilla/myns/PMyManagerChild.h</span></code>, respectively. The namespace becomes part of the path.</p> </section> <section id="generating-ipdl-aware-c-data-types-ipdl-structs-and-unions"> <h3>Generating IPDL-Aware C++ Data Types: IPDL Structs and Unions<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#generating-ipdl-aware-c-data-types-ipdl-structs-and-unions" title="Link to this heading">¶</a></h3> <p><code class="docutils literal notranslate"><span class="pre">PMyManager.ipdl</span></code> and <code class="docutils literal notranslate"><span class="pre">MyTypes.ipdlh</span></code> define:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="p">[</span><span class="n">Comparable</span><span class="p">]</span><span class="w"> </span><span class="k">union</span><span class="w"> </span><span class="nc">MyUnion</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="kt">float</span><span class="p">;</span> <span class="w"> </span><span class="n">MyOtherData</span><span class="p">;</span> <span class="p">};</span> <span class="k">struct</span><span class="w"> </span><span class="nc">MyActorPair</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">PMyManaged</span><span class="w"> </span><span class="n">actor1</span><span class="p">;</span> <span class="w"> </span><span class="n">nullable</span><span class="w"> </span><span class="n">PMyManaged</span><span class="w"> </span><span class="n">actor2</span><span class="p">;</span> <span class="p">};</span> </pre> </div> </div> <p>From these descriptions, IPDL generates C++ classes that approximate the behavior of C++ structs and unions but that come with pre-defined <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> implementations. These objects can also be used as usual outside of IPDL, although the lack of control over the generated code means they are sometimes poorly suited to use as plain data. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#paramtraits">ParamTraits</a> for details.</p> <p>The <code class="docutils literal notranslate"><span class="pre">[Comparable]</span></code> attribute tells IPDL to generate <code class="docutils literal notranslate"><span class="pre">operator==</span></code> and <code class="docutils literal notranslate"><span class="pre">operator!=</span></code> for the new type. In order for it to do that, the fields inside the new type need to define both of those operators.</p> <p>Finally, the <code class="docutils literal notranslate"><span class="pre">nullable</span></code> keyword indicates that, when serialized, the actor may be null. It is intended to help users avoid null-object dereference errors. It only applies to actor types and may also be attached to parameters in message declarations.</p> </section> <section id="defining-actors"> <h3>Defining Actors<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#defining-actors" title="Link to this heading">¶</a></h3> <p>The real point of any <code class="docutils literal notranslate"><span class="pre">.ipdl</span></code> file is that each defines exactly one actor protocol. The definition always matches the <code class="docutils literal notranslate"><span class="pre">.ipdl</span></code> filename. Repeating the one in <code class="docutils literal notranslate"><span class="pre">PMyManager.ipdl</span></code>:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="p">[</span><span class="n">ChildProc</span><span class="o">=</span><span class="n">Content</span><span class="p">]</span> <span class="n">sync</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManager</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">manages</span><span class="w"> </span><span class="n">PMyManaged</span><span class="p">;</span> <span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="nf">PMyManaged</span><span class="p">();</span> <span class="w"> </span><span class="c1">// ... more message declarations ...</span> <span class="p">};</span> </pre> </div> </div> <div class="admonition important"> <p class="admonition-title">Important</p> <p>A form of reference counting is <cite>always</cite> used internally by IPDL to make sure that it and its clients never address an actor the other component deleted but this becomes fragile, and sometimes fails, when the client code does not respect the reference count. For example, when IPDL detects that a connection died due to a crashed remote process, deleting the actor could leave dangling pointers, so IPDL <cite>cannot</cite> delete it. On the other hand, there are many cases where IPDL is the only entity to have references to some actors (this is very common for one side of a managed actor) so IPDL <cite>must</cite> delete it. If all of those objects were reference counted then there would be no complexity here. Indeed, new actors using <code class="docutils literal notranslate"><span class="pre">[ManualDealloc]</span></code> should not be approved without a very compelling reason. New <code class="docutils literal notranslate"><span class="pre">[ManualDealloc]</span></code> actors may soon be forbidden.</p> </div> <p>The <code class="docutils literal notranslate"><span class="pre">sync</span></code> keyword tells IPDL that the actor contains messages that block the sender using <code class="docutils literal notranslate"><span class="pre">sync</span></code> blocking, so the sending thread waits for a response to the message. There is more on what it and the other blocking modes mean in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#declaring-ipdl-messages">IPDL messages</a>. For now, just know that this is redundant information whose value is primarily in making it easy for other developers to know that there are <code class="docutils literal notranslate"><span class="pre">sync</span></code> messages defined here. This list gives preliminary definitions of the options for the actor-blocking policy of messages:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">async</span></code></p></td> <td><p>Actor may contain only asynchronous messages.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">sync</span></code></p></td> <td><p>Actor has <code class="docutils literal notranslate"><span class="pre">async</span></code> capabilities and adds <code class="docutils literal notranslate"><span class="pre">sync</span></code> messages. <code class="docutils literal notranslate"><span class="pre">sync</span></code> messages can only be sent from the child actor to the parent.</p></td> </tr> </tbody> </table> <p>Beyond these protocol blocking strategies, IPDL supports annotations that indicate the actor has messages that may be received in an order other than the one they were sent in. These orderings attempt to handle messages in “message thread” order (as in e.g. mailing lists). These behaviors can be difficult to design for. Their use is discouraged but is sometimes warranted. They will be discussed further in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#nested-messages">Nested messages</a>.</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[NestedUpTo=inside_sync]</span></code></p></td> <td><p>Actor has high priority messages that can be handled while waiting for a <code class="docutils literal notranslate"><span class="pre">sync</span></code> response.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[NestedUpTo=inside_cpow]</span></code></p></td> <td><p>Actor has the highest priority messages that can be handled while waiting for a <code class="docutils literal notranslate"><span class="pre">sync</span></code> response.</p></td> </tr> </tbody> </table> <p>In addition, top-level protocols are annotated with which processes each side should be bound into using the <code class="docutils literal notranslate"><span class="pre">[ParentProc=*]</span></code> and <code class="docutils literal notranslate"><span class="pre">[ChildProc=*]</span></code> attributes. The <code class="docutils literal notranslate"><span class="pre">[ParentProc]</span></code> attribute is optional, and defaults to the <code class="docutils literal notranslate"><span class="pre">Parent</span></code> process. The <code class="docutils literal notranslate"><span class="pre">[ChildProc]</span></code> attribute is required. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#process-type-attributes">Process Type Attributes</a> for possible values.</p> <p>The <code class="docutils literal notranslate"><span class="pre">manages</span></code> clause tells IPDL that <code class="docutils literal notranslate"><span class="pre">PMyManager</span></code> manages the <code class="docutils literal notranslate"><span class="pre">PMyManaged</span></code> actor that was previously <code class="docutils literal notranslate"><span class="pre">include</span></code> d. As with any managed protocol, it must also be the case that <code class="docutils literal notranslate"><span class="pre">PMyManaged.ipdl</span></code> includes <code class="docutils literal notranslate"><span class="pre">PMyManager</span></code> and declares that <code class="docutils literal notranslate"><span class="pre">PMyManaged</span></code> is <code class="docutils literal notranslate"><span class="pre">managed</span></code> by <code class="docutils literal notranslate"><span class="pre">PMyManager</span></code>. Recalling the code:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="c1">// PMyManaged.ipdl</span> <span class="n">include</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManager</span><span class="p">;</span> <span class="c1">// ...</span> <span class="n">protocol</span><span class="w"> </span><span class="n">PMyManaged</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">manager</span><span class="w"> </span><span class="n">PMyManager</span><span class="p">;</span> <span class="w"> </span><span class="c1">// ...</span> <span class="p">};</span> </pre> </div> </div> <p>An actor has a <code class="docutils literal notranslate"><span class="pre">manager</span></code> (e.g. <code class="docutils literal notranslate"><span class="pre">PMyManaged</span></code>) or else it is a top-level actor (e.g. <code class="docutils literal notranslate"><span class="pre">PMyManager</span></code>). An actor protocol may be managed by more than one actor type. For example, <code class="docutils literal notranslate"><span class="pre">PMyManaged</span></code> could have also been managed by some <code class="docutils literal notranslate"><span class="pre">PMyOtherManager</span></code> not shown here. In that case, <code class="docutils literal notranslate"><span class="pre">manager</span></code> s are presented in a list, separated by <code class="docutils literal notranslate"><span class="pre">or</span></code> – e.g. <code class="docutils literal notranslate"><span class="pre">manager</span> <span class="pre">PMyManager</span> <span class="pre">or</span> <span class="pre">PMyOtherManager</span></code>. Of course, an <strong>instance</strong> of a managed actor type has only one manager actor (and is therefore managed by only one of the types of manager). The manager of an instance of a managee is always the actor that constructed that managee.</p> <p>Finally, there is the message declaration <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">PMyManaged()</span></code>. This message is a constructor for <code class="docutils literal notranslate"><span class="pre">MyManaged</span></code> actors; unlike C++ classes, it is found in <code class="docutils literal notranslate"><span class="pre">MyManager</span></code>. Every manager will need to expose constructors to create its managed types. These constructors are the only way to create an actor that is managed. They can take parameters and return results, like normal messages. The implementation of IPDL constructors are discussed in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actor-lifetimes-in-c">Actor Lifetimes in C++</a>.</p> <p>We haven’t discussed a way to construct new top level actors. This is a more advanced topic and is covered separately in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#top-level-actors">Top Level Actors</a>.</p> </section> <section id="declaring-ipdl-messages"> <h3>Declaring IPDL Messages<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#declaring-ipdl-messages" title="Link to this heading">¶</a></h3> <p>The final part of the actor definition is the declaration of messages:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="n">sync</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManager</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// ...</span> <span class="w"> </span><span class="nl">parent</span><span class="p">:</span> <span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="nf">__delete__</span><span class="p">(</span><span class="n">nsString</span><span class="w"> </span><span class="n">aNote</span><span class="p">);</span> <span class="w"> </span><span class="n">sync</span><span class="w"> </span><span class="nf">SomeMsg</span><span class="p">(</span><span class="n">MyActorPair</span><span class="o">?</span><span class="w"> </span><span class="n">aActors</span><span class="p">,</span><span class="w"> </span><span class="n">MyData</span><span class="p">[]</span><span class="w"> </span><span class="n">aMyData</span><span class="p">)</span> <span class="w"> </span><span class="n">returns</span><span class="w"> </span><span class="p">(</span><span class="kt">int32_t</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="w"> </span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">MyUnion</span><span class="w"> </span><span class="n">aUnion</span><span class="p">);</span> <span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="nf">PMyManaged</span><span class="p">();</span> <span class="w"> </span><span class="nl">both</span><span class="p">:</span> <span class="w"> </span><span class="p">[</span><span class="n">Tainted</span><span class="p">]</span><span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="n">AnotherMsg</span><span class="p">(</span><span class="n">MyActorEnum</span><span class="w"> </span><span class="n">aEnum</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">number</span><span class="p">)</span> <span class="w"> </span><span class="n">returns</span><span class="w"> </span><span class="p">(</span><span class="n">MyOtherData</span><span class="w"> </span><span class="n">aOtherData</span><span class="p">);</span> <span class="p">};</span> </pre> </div> </div> <p>The messages are grouped into blocks by <code class="docutils literal notranslate"><span class="pre">parent:</span></code>, <code class="docutils literal notranslate"><span class="pre">child:</span></code> and <code class="docutils literal notranslate"><span class="pre">both:</span></code>. These labels work the way <code class="docutils literal notranslate"><span class="pre">public:</span></code> and <code class="docutils literal notranslate"><span class="pre">private:</span></code> work in C++ – messages after these descriptors are sent/received (only) in the direction specified.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>As a mnemonic to remember which direction they indicate, remember to put the word “to” in front of them. So, for example, <code class="docutils literal notranslate"><span class="pre">parent:</span></code> precedes <code class="docutils literal notranslate"><span class="pre">__delete__</span></code>, meaning <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> is sent from the child <strong>to</strong> the parent, and <code class="docutils literal notranslate"><span class="pre">both:</span></code> states that <code class="docutils literal notranslate"><span class="pre">AnotherMsg</span></code> can be sent <strong>to</strong> either endpoint.</p> </div> <p>IPDL messages support the following annotations:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[Compress]</span></code></p></td> <td><p>Indicates repeated messages of this type will consolidate.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[Tainted]</span></code></p></td> <td><p>Parameters are required to be validated before using them.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[Priority=Foo]</span></code></p></td> <td><p>Priority of <code class="docutils literal notranslate"><span class="pre">MessageTask</span></code> that runs the C++ message handler. <code class="docutils literal notranslate"><span class="pre">Foo</span></code> is one of: <code class="docutils literal notranslate"><span class="pre">normal</span></code>, <code class="docutils literal notranslate"><span class="pre">input</span></code>, <code class="docutils literal notranslate"><span class="pre">vsync</span></code>, <code class="docutils literal notranslate"><span class="pre">mediumhigh</span></code>, or <code class="docutils literal notranslate"><span class="pre">control</span></code>. See the <code class="docutils literal notranslate"><span class="pre">IPC::Message::PriorityValue</span></code> enum.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[Nested=inside_sync]</span></code></p></td> <td><p>Indicates that the message can sometimes be handled while a sync message waits for a response.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[Nested=inside_cpow]</span></code></p></td> <td><p>Indicates that the message can sometimes be handled while a sync message waits for a response.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[LazySend]</span></code></p></td> <td><p>Messages with this annotation will be queued up to be sent together either immediately before a non-LazySend message, or from a direct task.</p></td> </tr> </tbody> </table> <p><code class="docutils literal notranslate"><span class="pre">[Compress]</span></code> provides crude protection against spamming with a flood of messages. When messages of type <code class="docutils literal notranslate"><span class="pre">M</span></code> are compressed, the queue of unprocessed messages between actors will never contain an <code class="docutils literal notranslate"><span class="pre">M</span></code> beside another one; they will always be separated by a message of a different type. This is achieved by throwing out the older of the two messages if sending the new one would break the rule. This has been used to throttle pointer events between the main and content processes.</p> <p><code class="docutils literal notranslate"><span class="pre">[Compress=all]</span></code> is similar but applies whether or not the messages are adjacent in the message queue.</p> <p><code class="docutils literal notranslate"><span class="pre">[Tainted]</span></code> is a C++ mechanism designed to encourage paying attentiton to parameter security. The values of tainted parameters cannot be used until you vouch for their safety. They are discussed in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actors-and-messages-in-c">Actors and Messages in C++</a>.</p> <p>The <code class="docutils literal notranslate"><span class="pre">Nested</span></code> annotations are deeply related to the message’s blocking policy that follows it and which was briefly discussed in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#defining-actors">Defining Actors</a>. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#nested-messages">Nested messages</a> for details.</p> <p><code class="docutils literal notranslate"><span class="pre">[LazySend]</span></code> indicates the message doesn’t need to be sent immediately, and can be sent later, from a direct task. Worker threads which do not support direct task dispatch will ignore this attribute. Messages with this annotation will still be delivered in-order with other messages, meaning that if a normal message is sent, any queued <code class="docutils literal notranslate"><span class="pre">[LazySend]</span></code> messages will be sent first. The attribute allows the transport layer to combine messages to be sent together, potentially reducing thread wake-ups for I/O and receiving threads.</p> <p>The following is a complete list of the available blocking policies. It resembles the list in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#defining-actors">Defining Actors</a>:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">async</span></code></p></td> <td><p>Actor may contain only asynchronous messages.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">sync</span></code></p></td> <td><p>Actor has <code class="docutils literal notranslate"><span class="pre">async</span></code> capabilities and adds <code class="docutils literal notranslate"><span class="pre">sync</span></code> messages. <code class="docutils literal notranslate"><span class="pre">sync</span></code> messages can only be sent from the child actor to the parent.</p></td> </tr> </tbody> </table> <p>The policy defines whether an actor will wait for a response when it sends a certain type of message. A <code class="docutils literal notranslate"><span class="pre">sync</span></code> actor will wait immediately after sending a <code class="docutils literal notranslate"><span class="pre">sync</span></code> message, stalling its thread, until a response is received. This is an easy source of browser stalls. It is rarely required that a message be synchronous. New <code class="docutils literal notranslate"><span class="pre">sync</span></code> messages are therefore required to get approval from an IPC peer. The IPDL compiler will require such messages to be listed in the file <code class="docutils literal notranslate"><span class="pre">sync-messages.ini</span></code>.</p> <p>The notion that only child actors can send <code class="docutils literal notranslate"><span class="pre">sync</span></code> messages was introduced to avoid potential deadlocks. It relies on the belief that a cycle (deadlock) of sync messages is impossible because they all point in one direction. This is no longer the case because any endpoint can be a child <cite>or</cite> parent and some, like the main process, sometimes serve as both. This means that sync messages should be used with extreme care.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>The notion of sync messages flowing in one direction is still the main mechanism IPDL uses to avoid deadlock. New actors should avoid violating this rule as the consequences are severe (and complex). Actors that break these rules should not be approved without <strong>extreme</strong> extenuating circumstances. If you think you need this, check with the IPC team on Element first (#ipc).</p> </div> <p>An <code class="docutils literal notranslate"><span class="pre">async</span></code> actor will not wait. An <code class="docutils literal notranslate"><span class="pre">async</span></code> response is essentially identical to sending another <code class="docutils literal notranslate"><span class="pre">async</span></code> message back. It may be handled whenever received messages are handled. The value over an <code class="docutils literal notranslate"><span class="pre">async</span></code> response message comes in the ergonomics – async responses are usually handled by C++ lambda functions that are more like continuations than methods. This makes them easier to write and to read. Additionally, they allow a response to return message failure, while there would be no such response if we were expecting to send a new async message back, and it failed.</p> <p>Following synchronization is the name of the message and its parameter list. The message <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> stands out as strange – indeed, it terminates the actor’s connection. <cite>It does not delete any actor objects itself!</cite> It severs the connections of the actor <cite>and any actors it manages</cite> at both endpoints. An actor will never send or receive any messages after it sends or receives a <code class="docutils literal notranslate"><span class="pre">__delete__</span></code>. Note that all sends and receives have to happen on a specific <em>worker</em> thread for any actor tree so the send/receive order is well defined. Anything sent after the actor processes <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> is ignored (send returns an error, messages yet to be received fail their delivery). In other words, some future operations may fail but no unexpected behavior is possible.</p> <p>In our example, the child can break the connection by sending <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> to the parent. The only thing the parent can do to sever the connection is to fail, such as by crashing. This sort of unidirectional control is both common and desirable.</p> <p><code class="docutils literal notranslate"><span class="pre">PMyManaged()</span></code> is a managed actor constructor. Note the asymmetry – an actor contains its managed actor’s constructors but its own destructor.</p> <p>The list of parameters to a message is fairly straight-forward. Parameters can be any type that has a C++ <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> specialization and is imported by a directive. That said, there are some surprises in the list of messages:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">int32_t</span></code>,…</p></td> <td><p>The standard primitive types are included. See <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/source/ipc/ipdl/ipdl/builtin.py">builtin.py</a> for a list. Pointer types are, unsurprisingly, forbidden.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">?</span></code></p></td> <td><p>When following a type T, the parameter is translated into <code class="docutils literal notranslate"><span class="pre">Maybe<T></span></code> in C++.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[]</span></code></p></td> <td><p>When following a type T, the parameter is translated into <code class="docutils literal notranslate"><span class="pre">nsTArray<T></span></code> in C++.</p></td> </tr> </tbody> </table> <p>Finally, the returns list declares the information sent in response, also as a tuple of typed parameters. As previously mentioned, even <code class="docutils literal notranslate"><span class="pre">async</span></code> messages can receive responses. A <code class="docutils literal notranslate"><span class="pre">sync</span></code> message will always wait for a response but an <code class="docutils literal notranslate"><span class="pre">async</span></code> message will not get one unless it has a <code class="docutils literal notranslate"><span class="pre">returns</span></code> clause.</p> <p>This concludes our tour of the IPDL example file. The connection to C++ is discussed in the next chapter; messages in particular are covered in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actors-and-messages-in-c">Actors and Messages in C++</a>. For suggestions on best practices when designing your IPDL actor approach, see <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#ipdl-best-practices">IPDL Best Practices</a>.</p> </section> <section id="ipdl-syntax-quick-reference"> <h3>IPDL Syntax Quick Reference<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#ipdl-syntax-quick-reference" title="Link to this heading">¶</a></h3> <p>The following is a list of the keywords and operators that have been introduced for use in IPDL files:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">include</span></code></p></td> <td><p>Include a C++ header (quoted file name) or <code class="docutils literal notranslate"><span class="pre">.ipdlh</span></code> file (unquoted with no file suffix).</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">using</span> <span class="pre">(class|struct)</span> <span class="pre">from</span></code></p></td> <td><p>Similar to <code class="docutils literal notranslate"><span class="pre">include</span></code> but imports only a specific data type.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">include</span> <span class="pre">protocol</span></code></p></td> <td><p>Include another actor for use in management statements, IPDL data types or as parameters to messages.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[RefCounted]</span></code></p></td> <td><p>Indicates that the imported C++ data types are reference counted. Refcounted types require a different <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> interface than non-reference-counted types.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[ManualDealloc]</span></code></p></td> <td><p>Indicates that the IPDL interface uses the legacy manual allocation/deallocation interface, rather than modern reference counting.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[MoveOnly]</span></code></p></td> <td><p>Indicates that an imported C++ data type should not be copied. IPDL code will move it instead.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">namespace</span></code></p></td> <td><p>Specifies the namespace for IPDL generated code.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">union</span></code></p></td> <td><p>An IPDL union definition.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">struct</span></code></p></td> <td><p>An IPDL struct definition.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[Comparable]</span></code></p></td> <td><p>Indicates that IPDL should generate <code class="docutils literal notranslate"><span class="pre">operator==</span></code> and <code class="docutils literal notranslate"><span class="pre">operator!=</span></code> for the given IPDL struct/union.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">nullable</span></code></p></td> <td><p>Indicates that an actor reference in an IPDL type may be null when sent over IPC.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">protocol</span></code></p></td> <td><p>An IPDL protocol (actor) definition.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">sync/async</span></code></p></td> <td><p>These are used in two cases: (1) to indicate whether a message blocks as it waits for a result and (2) because an actor that contains <code class="docutils literal notranslate"><span class="pre">sync</span></code> messages must itself be labeled <code class="docutils literal notranslate"><span class="pre">sync</span></code>.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[NestedUpTo=inside_sync]</span></code></p></td> <td><p>Indicates that an actor contains [Nested=inside_sync] messages, in addition to normal messages.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[NestedUpTo=inside_cpow]</span></code></p></td> <td><p>Indicates that an actor contains [Nested=inside_cpow] messages, in addition to normal messages.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[Nested=inside_sync]</span></code></p></td> <td><p>Indicates that the message can be handled while waiting for lower-priority, or in-message-thread, sync responses.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[Nested=inside_cpow]</span></code></p></td> <td><p>Indicates that the message can be handled while waiting for lower-priority, or in-message-thread, sync responses. Cannot be sent by the parent actor.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">manager</span></code></p></td> <td><p>Used in a protocol definition to indicate that this actor manages another one.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">manages</span></code></p></td> <td><p>Used in a protocol definition to indicate that this actor is managed by another one.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">or</span></code></p></td> <td><p>Used in a <code class="docutils literal notranslate"><span class="pre">manager</span></code> clause for actors that have multiple potential managers.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">parent:</span> <span class="pre">/</span> <span class="pre">child:</span> <span class="pre">/</span> <span class="pre">both:</span></code></p></td> <td><p>Indicates direction of subsequent actor messages. As a mnemonic to remember which direction they indicate, put the word “to” in front of them.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">returns</span></code></p></td> <td><p>Defines return values for messages. All types of message, including <code class="docutils literal notranslate"><span class="pre">async</span></code>, support returning values.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">__delete__</span></code></p></td> <td><p>A special message that destroys the related actors at both endpoints when sent. <code class="docutils literal notranslate"><span class="pre">Recv__delete__</span></code> and <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> are called before destroying the actor at the other endpoint, to allow for cleanup.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">int32_t</span></code>,…</p></td> <td><p>The standard primitive types are included.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">String</span></code></p></td> <td><p>Translated into <code class="docutils literal notranslate"><span class="pre">nsString</span></code> in C++.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">?</span></code></p></td> <td><p>When following a type T in an IPDL data structure or message parameter, the parameter is translated into <code class="docutils literal notranslate"><span class="pre">Maybe<T></span></code> in C++.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[]</span></code></p></td> <td><p>When following a type T in an IPDL data structure or message parameter, the parameter is translated into <code class="docutils literal notranslate"><span class="pre">nsTArray<T></span></code> in C++.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[Tainted]</span></code></p></td> <td><p>Used to indicate that a message’s handler should receive parameters that it is required to manually validate. Parameters of type <code class="docutils literal notranslate"><span class="pre">T</span></code> become <code class="docutils literal notranslate"><span class="pre">Tainted<T></span></code> in C++.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[Compress]</span></code></p></td> <td><p>Indicates repeated messages of this type will consolidate. When two messages of this type are sent and end up side-by-side in the message queue then the older message is discarded (not sent).</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[Compress=all]</span></code></p></td> <td><p>Like <code class="docutils literal notranslate"><span class="pre">[Compress]</span></code> but discards the older message regardless of whether they are adjacent in the message queue.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[Priority=Foo]</span></code></p></td> <td><p>Priority of <code class="docutils literal notranslate"><span class="pre">MessageTask</span></code> that runs the C++ message handler. <code class="docutils literal notranslate"><span class="pre">Foo</span></code> is one of: <code class="docutils literal notranslate"><span class="pre">normal</span></code>, <code class="docutils literal notranslate"><span class="pre">input</span></code>, <code class="docutils literal notranslate"><span class="pre">vsync</span></code>, <code class="docutils literal notranslate"><span class="pre">mediumhigh</span></code>, or <code class="docutils literal notranslate"><span class="pre">control</span></code>.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[LazySend]</span></code></p></td> <td><p>Messages with this annotation will be queued up to be sent together immediately before a non-LazySend message, or from a direct task.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[ChildImpl="RemoteFoo"]</span></code></p></td> <td><p>Indicates that the child side implementation of the actor is a class named <code class="docutils literal notranslate"><span class="pre">RemoteFoo</span></code>, and the definition is included by one of the <code class="docutils literal notranslate"><span class="pre">include</span> <span class="pre">"...";</span></code> statements in the file. <em>New uses of this attribute are discouraged.</em></p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[ParentImpl="FooImpl"]</span></code></p></td> <td><p>Indicates that the parent side implementation of the actor is a class named <code class="docutils literal notranslate"><span class="pre">FooImpl</span></code>, and the definition is included by one of the <code class="docutils literal notranslate"><span class="pre">include</span> <span class="pre">"...";</span></code> statements in the file. <em>New uses of this attribute are discouraged.</em></p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[ChildImpl=virtual]</span></code></p></td> <td><p>Indicates that the child side implementation of the actor is not exported by a header, so virtual <code class="docutils literal notranslate"><span class="pre">Recv</span></code> methods should be used instead of direct function calls. <em>New uses of this attribute are discouraged.</em></p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[ParentImpl=virtual]</span></code></p></td> <td><p>Indicates that the parent side implementation of the actor is not exported by a header, so virtual <code class="docutils literal notranslate"><span class="pre">Recv</span></code> methods should be used instead of direct function calls. <em>New uses of this attribute are discouraged.</em></p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[ChildProc=...]</span></code></p></td> <td><p>Indicates which process the child side of the actor is expected to be bound in. This will be release asserted when creating the actor. Required for top-level actors. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#process-type-attributes">Process Type Attributes</a> for possible values.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[ParentProc=...]</span></code></p></td> <td><p>Indicates which process the parent side of the actor is expected to be bound in. This will be release asserted when creating the actor. Defaults to <code class="docutils literal notranslate"><span class="pre">Parent</span></code> for top-level actors. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#process-type-attributes">Process Type Attributes</a> for possible values.</p></td> </tr> </tbody> </table> <section id="process-type-attributes"><span id="id1"></span> <h4>Process Type Attributes<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#process-type-attributes" title="Link to this heading">¶</a></h4> <p>The following are valid values for the <code class="docutils literal notranslate"><span class="pre">[ChildProc=...]</span></code> and <code class="docutils literal notranslate"><span class="pre">[ParentProc=...]</span></code> attributes on protocols, each corresponding to a specific process type:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">Parent</span></code></p></td> <td><p>The primary “parent” or “main” process</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">Content</span></code></p></td> <td><p>A content process, such as those used to host web pages, workers, and extensions</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">IPDLUnitTest</span></code></p></td> <td><p>Test-only process used in IPDL gtests</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">GMPlugin</span></code></p></td> <td><p>Gecko Media Plugin (GMP) process</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">GPU</span></code></p></td> <td><p>GPU process</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">VR</span></code></p></td> <td><p>VR process</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">RDD</span></code></p></td> <td><p>Remote Data Decoder (RDD) process</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">Socket</span></code></p></td> <td><p>Socket/Networking process</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">ForkServer</span></code></p></td> <td><p>Fork Server process</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">Utility</span></code></p></td> <td><p>Utility process</p></td> </tr> </tbody> </table> <p>The attributes also support some wildcard values, which can be used when an actor can be bound in multiple processes. If you are adding an actor which needs a new wildcard value, please reach out to the IPC team, and we can add one for your use-case. They are as follows:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">any</span></code></p></td> <td><p>Any process. If a more specific value is applicable, it should be preferred where possible.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">anychild</span></code></p></td> <td><p>Any process other than <code class="docutils literal notranslate"><span class="pre">Parent</span></code>. Often used for utility actors which are bound on a per-process basis, such as profiling.</p></td> </tr> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">compositor</span></code></p></td> <td><p>Either the <code class="docutils literal notranslate"><span class="pre">GPU</span></code> or <code class="docutils literal notranslate"><span class="pre">Parent</span></code> process. Often used for actors bound to the compositor thread.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">anydom</span></code></p></td> <td><p>Either the <code class="docutils literal notranslate"><span class="pre">Parent</span></code> or a <code class="docutils literal notranslate"><span class="pre">Content</span></code> process. Often used for actors used to implement DOM APIs.</p></td> </tr> </tbody> </table> <p>Note that these assertions do not provide security guarantees, and are primarily intended for use when auditing and as documentation for how actors are being used.</p> </section> </section> </section> <section id="the-c-interface"> <h2>The C++ Interface<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-c-interface" title="Link to this heading">¶</a></h2> <section id="paramtraits"> <h3>ParamTraits<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#paramtraits" title="Link to this heading">¶</a></h3> <p>Before discussing how C++ represents actors and messages, we look at how IPDL connects to the imported C++ data types. In order for any C++ type to be (de)serialized, it needs an implementation of the <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> C++ type class. <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> is how your code tells IPDL what bytes to write to serialize your objects for sending, and how to convert those bytes back to objects at the other endpoint. Since <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> need to be reachable by IPDL code, they need to be declared in a C++ header and imported by your protocol file. Failure to do so will result in a build error.</p> <p>Most basic types and many essential Mozilla types are always available for use without inclusion. An incomplete list includes: C++ primitives, strings (<code class="docutils literal notranslate"><span class="pre">std</span></code> and <code class="docutils literal notranslate"><span class="pre">mozilla</span></code>), vectors (<code class="docutils literal notranslate"><span class="pre">std</span></code> and <code class="docutils literal notranslate"><span class="pre">mozilla</span></code>), <code class="docutils literal notranslate"><span class="pre">RefPtr<T></span></code> (for serializable <code class="docutils literal notranslate"><span class="pre">T</span></code>), <code class="docutils literal notranslate"><span class="pre">UniquePtr<T></span></code>, <code class="docutils literal notranslate"><span class="pre">nsCOMPtr<T></span></code>, <code class="docutils literal notranslate"><span class="pre">nsTArray<T></span></code>, <code class="docutils literal notranslate"><span class="pre">std::unordered_map<T></span></code>, <code class="docutils literal notranslate"><span class="pre">nsresult</span></code>, etc. See <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/source/ipc/ipdl/ipdl/builtin.py">builtin.py</a>, <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/source/ipc/chromium/src/chrome/common/ipc_message_utils.h">ipc_message_utils.h</a> and <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/source/ipc/glue/IPCMessageUtilsSpecializations.h">IPCMessageUtilsSpecializations.h</a>.</p> <p><code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> typically bootstrap with the <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> of more basic types, until they hit bedrock (e.g. one of the basic types above). In the most extreme cases, a <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> author may have to resort to designing a binary data format for a type. Both options are available.</p> <p>We haven’t seen any of this C++ yet. Let’s look at the data types included from <code class="docutils literal notranslate"><span class="pre">MyDataTypes.h</span></code>:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="c1">// MyDataTypes.h</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">mozilla</span><span class="o">::</span><span class="nn">myns</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">MyData</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">nsCString</span><span class="w"> </span><span class="n">s</span><span class="p">;</span> <span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">bytes</span><span class="p">[</span><span class="mi">17</span><span class="p">];</span> <span class="w"> </span><span class="n">MyData</span><span class="p">();</span><span class="w"> </span><span class="c1">// IPDL requires the default constructor to be public</span> <span class="w"> </span><span class="p">};</span> <span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">MoveonlyData</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">MoveonlyData</span><span class="p">();</span> <span class="w"> </span><span class="n">MoveonlyData</span><span class="o">&</span><span class="w"> </span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">MoveonlyData</span><span class="o">&</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">delete</span><span class="p">;</span> <span class="w"> </span><span class="n">MoveonlyData</span><span class="p">(</span><span class="n">MoveonlyData</span><span class="o">&&</span><span class="w"> </span><span class="n">m</span><span class="p">);</span> <span class="w"> </span><span class="n">MoveonlyData</span><span class="o">&</span><span class="w"> </span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">MoveonlyData</span><span class="o">&&</span><span class="w"> </span><span class="n">m</span><span class="p">);</span> <span class="w"> </span><span class="p">};</span> <span class="w"> </span><span class="k">typedef</span><span class="w"> </span><span class="n">MoveonlyData</span><span class="w"> </span><span class="n">MyOtherData</span><span class="p">;</span> <span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">MyUnusedData</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">public</span><span class="o">:</span> <span class="w"> </span><span class="n">NS_INLINE_DECL_REFCOUNTING</span><span class="p">(</span><span class="n">MyUnusedData</span><span class="p">)</span> <span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">;</span> <span class="w"> </span><span class="p">};</span> <span class="p">};</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">IPC</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// Basic type</span> <span class="w"> </span><span class="k">template</span><span class="o"><></span> <span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ParamTraits</span><span class="o"><</span><span class="n">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyData</span><span class="o">></span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">typedef</span><span class="w"> </span><span class="n">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyData</span><span class="w"> </span><span class="n">paramType</span><span class="p">;</span> <span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Write</span><span class="p">(</span><span class="n">MessageWriter</span><span class="o">*</span><span class="w"> </span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">paramType</span><span class="o">&</span><span class="w"> </span><span class="n">in</span><span class="p">);</span> <span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="nf">Read</span><span class="p">(</span><span class="n">MessageReader</span><span class="o">*</span><span class="w"> </span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">paramType</span><span class="o">*</span><span class="w"> </span><span class="n">out</span><span class="p">);</span> <span class="w"> </span><span class="p">};</span> <span class="w"> </span><span class="c1">// [MoveOnly] type</span> <span class="w"> </span><span class="k">template</span><span class="o"><></span> <span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ParamTraits</span><span class="o"><</span><span class="n">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyOtherData</span><span class="o">></span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">typedef</span><span class="w"> </span><span class="n">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyOtherData</span><span class="w"> </span><span class="n">paramType</span><span class="p">;</span> <span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Write</span><span class="p">(</span><span class="n">MessageWriter</span><span class="o">*</span><span class="w"> </span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">paramType</span><span class="o">&</span><span class="w"> </span><span class="n">in</span><span class="p">);</span> <span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="nf">Read</span><span class="p">(</span><span class="n">MessageReader</span><span class="o">*</span><span class="w"> </span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">paramType</span><span class="o">*</span><span class="w"> </span><span class="n">out</span><span class="p">);</span> <span class="w"> </span><span class="p">};</span> <span class="w"> </span><span class="c1">// [RefCounted] type</span> <span class="w"> </span><span class="k">template</span><span class="o"><></span> <span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ParamTraits</span><span class="o"><</span><span class="n">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyUnusedData</span><span class="o">*></span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">typedef</span><span class="w"> </span><span class="n">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyUnusedData</span><span class="w"> </span><span class="n">paramType</span><span class="p">;</span> <span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Write</span><span class="p">(</span><span class="n">MessageWriter</span><span class="o">*</span><span class="w"> </span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">paramType</span><span class="o">*</span><span class="w"> </span><span class="n">in</span><span class="p">);</span> <span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="nf">Read</span><span class="p">(</span><span class="n">MessageReader</span><span class="o">*</span><span class="w"> </span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">RefPtr</span><span class="o"><</span><span class="n">paramType</span><span class="o">>*</span><span class="w"> </span><span class="n">out</span><span class="p">);</span> <span class="w"> </span><span class="p">};</span> <span class="p">}</span> </pre> </div> </div> <p>MyData is a struct and MyOtherData is a typedef. IPDL is fine with both. Additionally, MyOtherData is not copyable, matching its IPDL <code class="docutils literal notranslate"><span class="pre">[MoveOnly]</span></code> annotation.</p> <p><code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> are required to be defined in the <code class="docutils literal notranslate"><span class="pre">IPC</span></code> namespace. They must contain a <code class="docutils literal notranslate"><span class="pre">Write</span></code> method with the proper signature that is used for serialization and a <code class="docutils literal notranslate"><span class="pre">Read</span></code> method, again with the correct signature, for deserialization.</p> <p>Here we have three examples of declarations: one for an unannotated type, one for <code class="docutils literal notranslate"><span class="pre">[MoveOnly]</span></code> and a <code class="docutils literal notranslate"><span class="pre">[RefCounted]</span></code> one. Notice the difference in the <code class="docutils literal notranslate"><span class="pre">[RefCounted]</span></code> type’s method signatures. The only difference that may not be clear from the function types is that, in the non-reference-counted case, a default-constructed object is supplied to <code class="docutils literal notranslate"><span class="pre">Read</span></code> but, in the reference-counted case, <code class="docutils literal notranslate"><span class="pre">Read</span></code> is given an empty <code class="docutils literal notranslate"><span class="pre">RefPtr<MyUnusedData></span></code> and should only allocate a <code class="docutils literal notranslate"><span class="pre">MyUnusedData</span></code> to return if it so desires.</p> <p>These are straight-forward implementations of the <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> methods for <code class="docutils literal notranslate"><span class="pre">MyData</span></code>:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="cm">/* static */</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">IPC</span><span class="o">::</span><span class="n">ParamTraits</span><span class="o"><</span><span class="n">MyData</span><span class="o">>::</span><span class="n">Write</span><span class="p">(</span><span class="n">MessageWriter</span><span class="o">*</span><span class="w"> </span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">paramType</span><span class="o">&</span><span class="w"> </span><span class="n">in</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">WriteParam</span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">in</span><span class="p">.</span><span class="n">s</span><span class="p">);</span> <span class="w"> </span><span class="n">m</span><span class="o">-></span><span class="n">WriteBytes</span><span class="p">(</span><span class="n">in</span><span class="p">.</span><span class="n">bytes</span><span class="p">,</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">in</span><span class="p">.</span><span class="n">bytes</span><span class="p">));</span> <span class="p">}</span> <span class="cm">/* static */</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">IPC</span><span class="o">::</span><span class="n">ParamTraits</span><span class="o"><</span><span class="n">MyData</span><span class="o">>::</span><span class="n">Read</span><span class="p">(</span><span class="n">MessageReader</span><span class="o">*</span><span class="w"> </span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">paramType</span><span class="o">*</span><span class="w"> </span><span class="n">out</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">ReadParam</span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">out</span><span class="o">-></span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span> <span class="w"> </span><span class="n">m</span><span class="o">-></span><span class="n">ReadBytesInto</span><span class="p">(</span><span class="n">out</span><span class="o">-></span><span class="n">bytes</span><span class="p">,</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">out</span><span class="o">-></span><span class="n">bytes</span><span class="p">));</span> <span class="p">}</span> </pre> </div> </div> <p><code class="docutils literal notranslate"><span class="pre">WriteParam</span></code> and <code class="docutils literal notranslate"><span class="pre">ReadParam</span></code> call the <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> for the data you pass them, determined using the type of the object as supplied. <code class="docutils literal notranslate"><span class="pre">WriteBytes</span></code> and <code class="docutils literal notranslate"><span class="pre">ReadBytesInto</span></code> work on raw, contiguous bytes as expected. <code class="docutils literal notranslate"><span class="pre">MessageWriter</span></code> and <code class="docutils literal notranslate"><span class="pre">MessageReader</span></code> are IPDL internal objects which hold the incoming/outgoing message as a stream of bytes and the current spot in the stream. It is <em>very</em> rare for client code to need to create or manipulate these objects. Their advanced use is beyond the scope of this document.</p> <div class="admonition important"> <p class="admonition-title">Important</p> <p>Potential failures in <code class="docutils literal notranslate"><span class="pre">Read</span></code> include everyday C++ failures like out-of-memory conditions, which can be handled as usual. But <code class="docutils literal notranslate"><span class="pre">Read</span></code> can also fail due to things like data validation errors. <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> read data that is considered insecure. It is important that they catch corruption and properly handle it. Returning false from <code class="docutils literal notranslate"><span class="pre">Read</span></code> will usually result in crashing the process (everywhere except in the main process). This is the right behavior as the browser would be in an unexpected state, even if the serialization failure was not malicious (since it cannot process the message). Other responses, such as failing with a crashing assertion, are inferior. IPDL fuzzing relies on <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> not crashing due to corruption failures. Occasionally, validation will require access to state that <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> can’t easily reach. (Only) in those cases, validation can be reasonably done in the message handler. Such cases are a good use of the <code class="docutils literal notranslate"><span class="pre">Tainted</span></code> annotation. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actors-and-messages-in-c">Actors and Messages in C++</a> for more.</p> </div> <div class="admonition note"> <p class="admonition-title">Note</p> <p>In the past, it was required to specialize <code class="docutils literal notranslate"><span class="pre">mozilla::ipc::IPDLParamTraits<T></span></code> instead of <code class="docutils literal notranslate"><span class="pre">IPC::ParamTraits<T></span></code> if you needed the actor object itself during serialization or deserialization. These days the actor can be fetched using <code class="docutils literal notranslate"><span class="pre">IPC::Message{Reader,Writer}::GetActor()</span></code> in <code class="docutils literal notranslate"><span class="pre">IPC::ParamTraits</span></code>, so that trait should be used for all new serializations.</p> </div> <p>A special case worth mentioning is that of enums. Enums are a common source of security holes since code is rarely safe with enum values that are not valid. Since data obtained through IPDL messages should be considered tainted, enums are of principal concern. <code class="docutils literal notranslate"><span class="pre">ContiguousEnumSerializer</span></code> and <code class="docutils literal notranslate"><span class="pre">ContiguousEnumSerializerInclusive</span></code> safely implement <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> for enums that are only valid for a contiguous set of values, which is most of them. The generated <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> confirm that the enum is in valid range; <code class="docutils literal notranslate"><span class="pre">Read</span></code> will return false otherwise. As an example, here is the <code class="docutils literal notranslate"><span class="pre">MyActorEnum</span></code> included from <code class="docutils literal notranslate"><span class="pre">MyActorUtils.h</span></code>:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="k">enum</span><span class="w"> </span><span class="nc">MyActorEnum</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">e1</span><span class="p">,</span><span class="w"> </span><span class="n">e2</span><span class="p">,</span><span class="w"> </span><span class="n">e3</span><span class="p">,</span><span class="w"> </span><span class="n">e4</span><span class="p">,</span><span class="w"> </span><span class="n">e5</span><span class="w"> </span><span class="p">};</span> <span class="k">template</span><span class="o"><></span> <span class="k">struct</span><span class="w"> </span><span class="nc">ParamTraits</span><span class="o"><</span><span class="n">MyActorEnum</span><span class="o">></span> <span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">ContiguousEnumSerializerInclusive</span><span class="o"><</span><span class="n">MyActorEnum</span><span class="p">,</span><span class="w"> </span><span class="n">MyActorEnum</span><span class="o">::</span><span class="n">e1</span><span class="p">,</span><span class="w"> </span><span class="n">MyActorEnum</span><span class="o">::</span><span class="n">e5</span><span class="o">></span><span class="w"> </span><span class="p">{};</span> </pre> </div> </div> </section> <section id="ipdl-structs-and-unions-in-c"> <h3>IPDL Structs and Unions in C++<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#ipdl-structs-and-unions-in-c" title="Link to this heading">¶</a></h3> <p>IPDL structs and unions become C++ classes that provide interfaces that are fairly self-explanatory. Recalling <code class="docutils literal notranslate"><span class="pre">MyUnion</span></code> and <code class="docutils literal notranslate"><span class="pre">MyActorPair</span></code> from <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#generating-ipdl-aware-c-data-types-ipdl-structs-and-unions">IPDL Structs and Unions</a> :</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="k">union</span><span class="w"> </span><span class="nc">MyUnion</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="kt">float</span><span class="p">;</span> <span class="w"> </span><span class="n">MyOtherData</span><span class="p">;</span> <span class="p">};</span> <span class="k">struct</span><span class="w"> </span><span class="nc">MyActorPair</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">PMyManaged</span><span class="w"> </span><span class="n">actor1</span><span class="p">;</span> <span class="w"> </span><span class="n">nullable</span><span class="w"> </span><span class="n">PMyManaged</span><span class="w"> </span><span class="n">actor2</span><span class="p">;</span> <span class="p">};</span> </pre> </div> </div> <p>These compile to:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyUnion</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">enum</span><span class="w"> </span><span class="nc">Type</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Tfloat</span><span class="p">,</span><span class="w"> </span><span class="n">TMyOtherData</span><span class="w"> </span><span class="p">};</span> <span class="w"> </span><span class="n">Type</span><span class="w"> </span><span class="nf">type</span><span class="p">();</span> <span class="w"> </span><span class="n">MyUnion</span><span class="p">(</span><span class="kt">float</span><span class="w"> </span><span class="n">f</span><span class="p">);</span> <span class="w"> </span><span class="n">MyUnion</span><span class="p">(</span><span class="n">MyOtherData</span><span class="o">&&</span><span class="w"> </span><span class="n">aOD</span><span class="p">);</span> <span class="w"> </span><span class="n">MyUnion</span><span class="o">&</span><span class="w"> </span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="kt">float</span><span class="w"> </span><span class="n">f</span><span class="p">);</span> <span class="w"> </span><span class="n">MyUnion</span><span class="o">&</span><span class="w"> </span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">MyOtherData</span><span class="o">&&</span><span class="w"> </span><span class="n">aOD</span><span class="p">);</span> <span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="kt">float</span><span class="o">&</span><span class="p">();</span> <span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">MyOtherData</span><span class="o">&</span><span class="p">();</span> <span class="p">};</span> <span class="k">class</span><span class="w"> </span><span class="nc">MyActorPair</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">MyActorPair</span><span class="p">(</span><span class="n">PMyManagedParent</span><span class="o">*</span><span class="w"> </span><span class="n">actor1Parent</span><span class="p">,</span><span class="w"> </span><span class="n">PMyManagedChild</span><span class="o">*</span><span class="w"> </span><span class="n">actor1Child</span><span class="p">,</span> <span class="w"> </span><span class="n">PMyManagedParent</span><span class="o">*</span><span class="w"> </span><span class="n">actor2Parent</span><span class="p">,</span><span class="w"> </span><span class="n">PMyManagedChild</span><span class="o">*</span><span class="w"> </span><span class="n">actor2Child</span><span class="p">);</span> <span class="w"> </span><span class="c1">// Exactly one of { actor1Parent(), actor1Child() } must be non-null.</span> <span class="w"> </span><span class="n">PMyManagedParent</span><span class="o">*&</span><span class="w"> </span><span class="nf">actor1Parent</span><span class="p">();</span> <span class="w"> </span><span class="n">PMyManagedChild</span><span class="o">*&</span><span class="w"> </span><span class="nf">actor1Child</span><span class="p">();</span> <span class="w"> </span><span class="c1">// As nullable, zero or one of { actor2Parent(), actor2Child() } will be non-null.</span> <span class="w"> </span><span class="n">PMyManagedParent</span><span class="o">*&</span><span class="w"> </span><span class="nf">actor2Parent</span><span class="p">();</span> <span class="w"> </span><span class="n">PMyManagedChild</span><span class="o">*&</span><span class="w"> </span><span class="nf">actor2Child</span><span class="p">();</span> <span class="p">}</span> </pre> </div> </div> <p>The generated <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> use the <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> for the types referenced by the IPDL struct or union. Fields respect any annotations for their type (see <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#referencing-externally-defined-data-types-ipdl-includes">IPDL Includes</a>). For example, a <code class="docutils literal notranslate"><span class="pre">[RefCounted]</span></code> type <code class="docutils literal notranslate"><span class="pre">T</span></code> generates <code class="docutils literal notranslate"><span class="pre">RefPtr<T></span></code> fields.</p> <p>Note that actor members result in members of both the parent and child actor types, as seen in <code class="docutils literal notranslate"><span class="pre">MyActorPair</span></code>. When actors are used to bridge processes, only one of those could ever be used at a given endpoint. IPDL makes sure that, when you send one type (say, <code class="docutils literal notranslate"><span class="pre">PMyManagedChild</span></code>), the adjacent actor of the other type (<code class="docutils literal notranslate"><span class="pre">PMyManagedParent</span></code>) is received. This is not only true for message parameters and IPDL structs/unions but also for custom <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code> implementations. If you <code class="docutils literal notranslate"><span class="pre">Write</span></code> a <code class="docutils literal notranslate"><span class="pre">PFooParent*</span></code> then you must <code class="docutils literal notranslate"><span class="pre">Read</span></code> a <code class="docutils literal notranslate"><span class="pre">PFooChild*</span></code>. This is hard to confuse in message handlers since they are members of a class named for the side they operate on, but this cannot be enforced by the compiler. If you are writing <code class="docutils literal notranslate"><span class="pre">MyManagerParent::RecvSomeMsg(Maybe<MyActorPair>&&</span> <span class="pre">aActors,</span> <span class="pre">nsTArray<MyData>&&</span> <span class="pre">aMyData)</span></code> then the <code class="docutils literal notranslate"><span class="pre">actor1Child</span></code> and <code class="docutils literal notranslate"><span class="pre">actor2Child</span></code> fields cannot be valid since the child (usually) exists in another process.</p> </section> <section id="actors-and-messages-in-c"> <h3>Actors and Messages in C++<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actors-and-messages-in-c" title="Link to this heading">¶</a></h3> <p>As mentioned in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#using-the-ipdl-compiler">Using The IPDL compiler</a>, the IPDL compiler generates two header files for the protocol <code class="docutils literal notranslate"><span class="pre">PMyManager</span></code>: <code class="docutils literal notranslate"><span class="pre">PMyManagerParent.h</span></code> and <code class="docutils literal notranslate"><span class="pre">PMyManagerChild.h</span></code>, which declare the actor’s base classes. There, we discussed how the headers are visible to C++ components that include <code class="docutils literal notranslate"><span class="pre">chromium-config.mozbuild</span></code>. We, in turn, always need to define two files that declare our actor implementation subclasses (<code class="docutils literal notranslate"><span class="pre">MyManagerParent.h</span></code> and <code class="docutils literal notranslate"><span class="pre">MyManagerChild.h</span></code>). The IPDL file looked like this:</p> <div class="highlight-c++ notranslate" id="id3"> <div class="highlight"> <pre><span></span><span class="n">include</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManaged</span><span class="p">;</span> <span class="n">include</span><span class="w"> </span><span class="n">MyTypes</span><span class="p">;</span><span class="w"> </span><span class="c1">// for MyActorPair</span> <span class="k">using</span><span class="w"> </span><span class="n">MyActorEnum</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/myns/MyActorUtils.h"</span><span class="p">;</span> <span class="k">using</span><span class="w"> </span><span class="n">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyData</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/MyDataTypes.h"</span><span class="p">;</span> <span class="p">[</span><span class="n">MoveOnly</span><span class="p">]</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyOtherData</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/MyDataTypes.h"</span><span class="p">;</span> <span class="p">[</span><span class="n">RefCounted</span><span class="p">]</span><span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">mozilla</span><span class="o">::</span><span class="n">myns</span><span class="o">::</span><span class="n">MyThirdData</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="s">"mozilla/MyDataTypes.h"</span><span class="p">;</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">mozilla</span><span class="w"> </span><span class="p">{</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">myns</span><span class="w"> </span><span class="p">{</span> <span class="p">[</span><span class="n">Comparable</span><span class="p">]</span><span class="w"> </span><span class="k">union</span><span class="w"> </span><span class="nc">MyUnion</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="kt">float</span><span class="p">;</span><span class="w"> </span> <span class="w"> </span><span class="n">MyOtherData</span><span class="p">;</span> <span class="p">};</span> <span class="p">[</span><span class="n">ChildProc</span><span class="o">=</span><span class="n">any</span><span class="p">]</span> <span class="n">sync</span><span class="w"> </span><span class="n">protocol</span><span class="w"> </span><span class="n">PMyManager</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">manages</span><span class="w"> </span><span class="n">PMyManaged</span><span class="p">;</span> <span class="w"> </span><span class="nl">parent</span><span class="p">:</span> <span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="nf">__delete__</span><span class="p">(</span><span class="n">nsString</span><span class="w"> </span><span class="n">aNote</span><span class="p">);</span> <span class="w"> </span><span class="n">sync</span><span class="w"> </span><span class="nf">SomeMsg</span><span class="p">(</span><span class="n">MyActorPair</span><span class="o">?</span><span class="w"> </span><span class="n">aActors</span><span class="p">,</span><span class="w"> </span><span class="n">MyData</span><span class="p">[]</span><span class="w"> </span><span class="n">aMyData</span><span class="p">)</span> <span class="w"> </span><span class="n">returns</span><span class="w"> </span><span class="p">(</span><span class="kt">int32_t</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="w"> </span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">MyUnion</span><span class="w"> </span><span class="n">aUnion</span><span class="p">);</span> <span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="nf">PMyManaged</span><span class="p">();</span> <span class="w"> </span><span class="nl">both</span><span class="p">:</span> <span class="w"> </span><span class="p">[</span><span class="n">Tainted</span><span class="p">]</span><span class="w"> </span><span class="n">async</span><span class="w"> </span><span class="n">AnotherMsg</span><span class="p">(</span><span class="n">MyActorEnum</span><span class="w"> </span><span class="n">aEnum</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="w"> </span><span class="n">aNumber</span><span class="p">)</span> <span class="w"> </span><span class="n">returns</span><span class="w"> </span><span class="p">(</span><span class="n">MyOtherData</span><span class="w"> </span><span class="n">aOtherData</span><span class="p">);</span> <span class="p">};</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace myns</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace mozilla</span> </pre> </div> </div> <p>So <code class="docutils literal notranslate"><span class="pre">MyManagerParent.h</span></code> looks like this:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">"PMyManagerParent.h"</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">mozilla</span><span class="w"> </span><span class="p">{</span> <span class="k">namespace</span><span class="w"> </span><span class="nn">myns</span><span class="w"> </span><span class="p">{</span> <span class="k">class</span><span class="w"> </span><span class="nc">MyManagerParent</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">PMyManagerParent</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">NS_INLINE_DECL_REFCOUNTING</span><span class="p">(</span><span class="n">MyManagerParent</span><span class="p">,</span><span class="w"> </span><span class="k">override</span><span class="p">)</span> <span class="k">protected</span><span class="o">:</span> <span class="w"> </span><span class="n">IPCResult</span><span class="w"> </span><span class="n">Recv__delete__</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">nsString</span><span class="o">&</span><span class="w"> </span><span class="n">aNote</span><span class="p">);</span> <span class="w"> </span><span class="n">IPCResult</span><span class="w"> </span><span class="nf">RecvSomeMsg</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Maybe</span><span class="o"><</span><span class="n">MyActorPair</span><span class="o">>&</span><span class="w"> </span><span class="n">aActors</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">nsTArray</span><span class="o"><</span><span class="n">MyData</span><span class="o">>&</span><span class="w"> </span><span class="n">aMyData</span><span class="p">,</span> <span class="w"> </span><span class="kt">int32_t</span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="o">*</span><span class="w"> </span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">MyUnion</span><span class="o">*</span><span class="w"> </span><span class="n">aUnion</span><span class="p">);</span> <span class="w"> </span><span class="n">IPCResult</span><span class="w"> </span><span class="nf">RecvAnotherMsg</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Tainted</span><span class="o"><</span><span class="n">MyActorEnum</span><span class="o">>&</span><span class="w"> </span><span class="n">aEnum</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">Tainted</span><span class="o"><</span><span class="kt">int32_t</span><span class="o">>&</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">number</span><span class="p">,</span> <span class="w"> </span><span class="n">AnotherMsgResolver</span><span class="o">&&</span><span class="w"> </span><span class="n">aResolver</span><span class="p">);</span> <span class="w"> </span><span class="n">already_AddRefed</span><span class="o"><</span><span class="n">PMyManagerParent</span><span class="o">></span><span class="w"> </span><span class="n">AllocPMyManagedParent</span><span class="p">();</span> <span class="w"> </span><span class="n">IPCResult</span><span class="w"> </span><span class="nf">RecvPMyManagedConstructor</span><span class="p">(</span><span class="n">PMyManagedConstructor</span><span class="o">*</span><span class="w"> </span><span class="n">aActor</span><span class="p">);</span> <span class="w"> </span><span class="c1">// ... etc ...</span> <span class="p">};</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace myns</span> <span class="p">}</span><span class="w"> </span><span class="c1">// namespace mozilla</span> </pre> </div> </div> <p>All messages that can be sent to the actor must be handled by <code class="docutils literal notranslate"><span class="pre">Recv</span></code> methods in the proper actor subclass. They should return <code class="docutils literal notranslate"><span class="pre">IPC_OK()</span></code> on success and <code class="docutils literal notranslate"><span class="pre">IPC_FAIL(actor,</span> <span class="pre">reason)</span></code> if an error occurred (where <code class="docutils literal notranslate"><span class="pre">actor</span></code> is <code class="docutils literal notranslate"><span class="pre">this</span></code> and <code class="docutils literal notranslate"><span class="pre">reason</span></code> is a human text explanation) that should be considered a failure to process the message. The handling of such a failure is specific to the process type.</p> <p><code class="docutils literal notranslate"><span class="pre">Recv</span></code> methods are called by IPDL by enqueueing a task to run them on the <code class="docutils literal notranslate"><span class="pre">MessageLoop</span></code> for the thread on which they are bound. This thread is the actor’s <em>worker thread</em>. All actors in a managed actor tree have the same worker thread – in other words, actors inherit the worker thread from their managers. Top level actors establish their worker thread when they are <em>bound</em>. More information on threads can be found in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#top-level-actors">Top Level Actors</a>. For the most part, client code will never engage with an IPDL actor outside of its worker thread.</p> <p>Received parameters become stack variables that are <code class="docutils literal notranslate"><span class="pre">std::move</span></code>-d into the <code class="docutils literal notranslate"><span class="pre">Recv</span></code> method. They can be received as a const l-value reference, rvalue-reference, or by value (type-permitting). <code class="docutils literal notranslate"><span class="pre">[MoveOnly]</span></code> types should not be received as const l-values. Return values for sync messages are assigned by writing to non-const (pointer) parameters. Return values for async messages are handled differently – they are passed to a resolver function. In our example, <code class="docutils literal notranslate"><span class="pre">AnotherMsgResolver</span></code> would be a <code class="docutils literal notranslate"><span class="pre">std::function<></span></code> and <code class="docutils literal notranslate"><span class="pre">aResolver</span></code> would be given the value to return by passing it a reference to a <code class="docutils literal notranslate"><span class="pre">MyOtherData</span></code> object.</p> <p><code class="docutils literal notranslate"><span class="pre">MyManagerParent</span></code> is also capable of <code class="docutils literal notranslate"><span class="pre">sending</span></code> an async message that returns a value: <code class="docutils literal notranslate"><span class="pre">AnotherMsg</span></code>. This is done with <code class="docutils literal notranslate"><span class="pre">SendAnotherMsg</span></code>, which is defined automatically by IPDL in the base class <code class="docutils literal notranslate"><span class="pre">PMyManagerParent</span></code>. There are two signatures for <code class="docutils literal notranslate"><span class="pre">Send</span></code> and they look like this:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="c1">// Return a Promise that IPDL will resolve with the response or reject.</span> <span class="n">RefPtr</span><span class="o"><</span><span class="n">MozPromise</span><span class="o"><</span><span class="n">MyOtherData</span><span class="p">,</span><span class="w"> </span><span class="n">ResponseRejectReason</span><span class="p">,</span><span class="w"> </span><span class="nb">true</span><span class="o">>></span> <span class="n">SendAnotherMsg</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">MyActorEnum</span><span class="o">&</span><span class="w"> </span><span class="n">aEnum</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">number</span><span class="p">);</span> <span class="c1">// Provide callbacks to process response / reject. The callbacks are just</span> <span class="c1">// std::functions.</span> <span class="kt">void</span><span class="w"> </span><span class="nf">SendAnotherMsg</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">MyActorEnum</span><span class="o">&</span><span class="w"> </span><span class="n">aEnum</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">number</span><span class="p">,</span> <span class="w"> </span><span class="n">ResolveCallback</span><span class="o"><</span><span class="n">MyOtherData</span><span class="o">>&&</span><span class="w"> </span><span class="n">aResolve</span><span class="p">,</span><span class="w"> </span><span class="n">RejectCallback</span><span class="o">&&</span><span class="w"> </span><span class="n">aReject</span><span class="p">);</span> </pre> </div> </div> <p>The response is usually handled by lambda functions defined at the site of the <code class="docutils literal notranslate"><span class="pre">Send</span></code> call, either by attaching them to the returned promise with e.g. <code class="docutils literal notranslate"><span class="pre">MozPromise::Then</span></code>, or by passing them as callback parameters. See docs on <code class="docutils literal notranslate"><span class="pre">MozPromise</span></code> for more on its use. The promise itself is either resolved or rejected by IPDL when a valid reply is received or when the endpoint determines that the communication failed. <code class="docutils literal notranslate"><span class="pre">ResponseRejectReason</span></code> is an enum IPDL provides to explain failures.</p> <p>Additionally, the <code class="docutils literal notranslate"><span class="pre">AnotherMsg</span></code> handler has <code class="docutils literal notranslate"><span class="pre">Tainted</span></code> parameters, as a result of the [Tainted] annotation in the protocol file. Recall that <code class="docutils literal notranslate"><span class="pre">Tainted</span></code> is used to force explicit validation of parameters in the message handler before their values can be used (as opposed to validation in <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code>). They therefore have access to any state that the message handler does. Their APIs, along with a list of macros that are used to validate them, are detailed <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/source/mfbt/Tainting.h">here</a>.</p> <p>Send methods that are not for async messages with return values follow a simpler form; they return a <code class="docutils literal notranslate"><span class="pre">bool</span></code> indicating success or failure and return response values in non-const parameters, as the <code class="docutils literal notranslate"><span class="pre">Recv</span></code> methods do. For example, <code class="docutils literal notranslate"><span class="pre">PMyManagerChild</span></code> defines this to send the sync message <code class="docutils literal notranslate"><span class="pre">SomeMsg</span></code>:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="c1">// generated in PMyManagerChild</span> <span class="kt">bool</span><span class="w"> </span><span class="nf">SendSomeMsg</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Maybe</span><span class="o"><</span><span class="n">MyActorPair</span><span class="o">>&</span><span class="w"> </span><span class="n">aActors</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">nsTArray</span><span class="o"><</span><span class="n">MyData</span><span class="o">>&</span><span class="w"> </span><span class="n">aMyData</span><span class="p">,</span> <span class="w"> </span><span class="kt">int32_t</span><span class="o">&</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="kt">int32_t</span><span class="o">&</span><span class="w"> </span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">MyUnion</span><span class="o">&</span><span class="w"> </span><span class="n">aUnion</span><span class="p">);</span> </pre> </div> </div> <p>Since it is sync, this method will not return to its caller until the response is received or an error is detected.</p> <p>All calls to <code class="docutils literal notranslate"><span class="pre">Send</span></code> methods, like all messages handler <code class="docutils literal notranslate"><span class="pre">Recv</span></code> methods, must only be called on the worker thread for the actor.</p> <p>Constructors, like the one for <code class="docutils literal notranslate"><span class="pre">MyManaged</span></code>, are clearly an exception to these rules. They are discussed in the next section.</p> </section> <section id="actor-lifetimes-in-c"><span id="id4"></span> <h3>Actor Lifetimes in C++<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#actor-lifetimes-in-c" title="Link to this heading">¶</a></h3> <p>The constructor message for <code class="docutils literal notranslate"><span class="pre">MyManaged</span></code> becomes <em>two</em> methods at the receiving end. <code class="docutils literal notranslate"><span class="pre">AllocPMyManagedParent</span></code> constructs the managed actor, then <code class="docutils literal notranslate"><span class="pre">RecvPMyManagedConstructor</span></code> is called to update the new actor. The following diagram shows the construction of the <code class="docutils literal notranslate"><span class="pre">MyManaged</span></code> actor pair:</p> <figure class="align-center" id="id7"> <pre class="mermaid"> %%{init: {'sequence': {'boxMargin': 4, 'actorMargin': 10} }}%% sequenceDiagram participant d as Driver participant mgdc as MyManagedChild participant mgrc as MyManagerChild participant ipc as IPC Child/Parent participant mgrp as MyManagerParent participant mgdp as MyManagedParent d->>mgdc: new mgdc->>d: [mgd_child] d->>mgrc: SendPMyManagedConstructor<br/>[mgd_child, params] mgrc->>ipc: Form actor pair<br/>[mgd_child, params] par mgdc->>ipc: early PMyManaged messages and ipc->>mgrp: AllocPMyManagedParent<br/>[params] mgrp->>mgdp: new mgdp->>mgrp: [mgd_parent] ipc->>mgrp: RecvPMyManagedConstructor<br/>[mgd_parent, params] mgrp->>mgdp: initialization ipc->>mgdp: early PMyManaged messages end Note over mgdc,mgdp: Bi-directional sending and receiving will now happen concurrently. </pre> <figcaption> <p><span class="caption-text">A <code class="docutils literal notranslate"><span class="pre">MyManaged</span></code> actor pair being created by some <code class="docutils literal notranslate"><span class="pre">Driver</span></code> object. Internal IPC objects in the parent and child processes are combined for compactness. Connected <strong>par</strong> blocks run concurrently. This shows that messages can be safely sent while the parent is still being constructed.</span><a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#id7" title="Link to this image">¶</a></p> </figcaption> </figure> <p>The next diagram shows the destruction of the <code class="docutils literal notranslate"><span class="pre">MyManaged</span></code> actor pair, as initiated by a call to <code class="docutils literal notranslate"><span class="pre">Send__delete__</span></code>. <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> is sent from the child process because that is the only side that can call it, as declared in the IPDL protocol file.</p> <figure class="align-center" id="id8"> <pre class="mermaid"> %%{init: {'sequence': {'boxMargin': 4, 'actorMargin': 10} }}%% sequenceDiagram participant d as Driver participant mgdc as MyManagedChild participant ipc as IPC Child/Parent participant mgdp as MyManagedParent d->>mgdc: Send__delete__ mgdc->>ipc: Disconnect<br/>actor pair par ipc->>mgdc: ActorDestroy ipc->>mgdc: Release and ipc->>mgdp: Recv__delete__ ipc->>mgdp: ActorDestroy ipc->>mgdp: Release end </pre> <figcaption> <p><span class="caption-text">A <code class="docutils literal notranslate"><span class="pre">MyManaged</span></code> actor pair being disconnected due to some <code class="docutils literal notranslate"><span class="pre">Driver</span></code> object in the child process sending <code class="docutils literal notranslate"><span class="pre">__delete__</span></code>.</span><a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#id8" title="Link to this image">¶</a></p> </figcaption> </figure> <p>Finally, let’s take a look at the behavior of an actor whose peer has been lost (e.g. due to a crashed process).</p> <figure class="align-center" id="id9"> <pre class="mermaid"> %%{init: {'sequence': {'boxMargin': 4, 'actorMargin': 10} }}%% sequenceDiagram participant mgdc as MyManagedChild participant ipc as IPC Child/Parent participant mgdp as MyManagedParent Note over mgdc: CRASH!!! ipc->>ipc: Notice fatal error. ipc->>mgdp: ActorDestroy ipc->>mgdp: Release </pre> <figcaption> <p><span class="caption-text">A <code class="docutils literal notranslate"><span class="pre">MyManaged</span></code> actor pair being disconnected when its peer is lost due to a fatal error. Note that <code class="docutils literal notranslate"><span class="pre">Recv__delete__</span></code> is not called.</span><a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#id9" title="Link to this image">¶</a></p> </figcaption> </figure> <p>The <code class="docutils literal notranslate"><span class="pre">Alloc</span></code> and <code class="docutils literal notranslate"><span class="pre">Recv...Constructor</span></code> methods are somewhat mirrored by <code class="docutils literal notranslate"><span class="pre">Recv__delete__</span></code> and <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> but there are a few differences. First, the <code class="docutils literal notranslate"><span class="pre">Alloc</span></code> method really does create the actor but the <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> method does not delete it. Additionally, <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> is run at <em>both</em> endpoints, during <code class="docutils literal notranslate"><span class="pre">Send__delete__</span></code> or after <code class="docutils literal notranslate"><span class="pre">Recv__delete__</span></code>. Finally and most importantly, <code class="docutils literal notranslate"><span class="pre">Recv__delete__</span></code> is only called if the <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> message is received but it may not be if, for example, the remote process crashes. <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code>, on the other hand, is guaranteed to run for <em>every</em> actor unless the process terminates uncleanly. For this reason, <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> is the right place for most actor shutdown code. <code class="docutils literal notranslate"><span class="pre">Recv__delete__</span></code> is rarely useful, although it is occasionally beneficial to have it receive some final data.</p> <p>The relevant part of the parent class looks like this:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyManagerParent</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">PMyManagerParent</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">already_AddRefed</span><span class="o"><</span><span class="n">PMyManagedParent</span><span class="o">></span><span class="w"> </span><span class="n">AllocPMyManagedParent</span><span class="p">();</span> <span class="w"> </span><span class="n">IPCResult</span><span class="w"> </span><span class="nf">RecvPMyManagedConstructor</span><span class="p">(</span><span class="n">PMyManagedParent</span><span class="o">*</span><span class="w"> </span><span class="n">aActor</span><span class="p">);</span> <span class="w"> </span><span class="n">IPCResult</span><span class="w"> </span><span class="nf">Recv__delete__</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">nsString</span><span class="o">&</span><span class="w"> </span><span class="n">aNote</span><span class="p">);</span> <span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">ActorDestroy</span><span class="p">(</span><span class="n">ActorDestroyReason</span><span class="w"> </span><span class="n">why</span><span class="p">);</span> <span class="w"> </span><span class="c1">// ... etc ...</span> <span class="p">};</span> </pre> </div> </div> <p>The <code class="docutils literal notranslate"><span class="pre">Alloc</span></code> method is required for managed actors that are constructed by IPDL receiving a <code class="docutils literal notranslate"><span class="pre">Send</span></code> message. It is not required for the actor at the endpoint that calls <code class="docutils literal notranslate"><span class="pre">Send</span></code>. The <code class="docutils literal notranslate"><span class="pre">Recv...Constructor</span></code> message is not required – it has a base implementation that does nothing.</p> <p>If the constructor message has parameters, they are sent to both methods. Parameters are given to the <code class="docutils literal notranslate"><span class="pre">Alloc</span></code> method by const reference but are moved into the <code class="docutils literal notranslate"><span class="pre">Recv</span></code> method. They differ in that messages can be sent from the <code class="docutils literal notranslate"><span class="pre">Recv</span></code> method but, in <code class="docutils literal notranslate"><span class="pre">Alloc</span></code>, the newly created actor is not yet operational.</p> <p>The <code class="docutils literal notranslate"><span class="pre">Send</span></code> method for a constructor is similarly different from other <code class="docutils literal notranslate"><span class="pre">Send</span></code> methods. In the child actor, ours looks like this:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="n">IPCResult</span><span class="w"> </span><span class="nf">SendPMyManagedConstructor</span><span class="p">(</span><span class="n">PMyManagedChild</span><span class="o">*</span><span class="w"> </span><span class="n">aActor</span><span class="p">);</span> </pre> </div> </div> <p>The method expects a <code class="docutils literal notranslate"><span class="pre">PMyManagedChild</span></code> that the caller will have constructed, presumably using <code class="docutils literal notranslate"><span class="pre">new</span></code> (this is why it does not require an <code class="docutils literal notranslate"><span class="pre">Alloc</span></code> method). Once <code class="docutils literal notranslate"><span class="pre">Send...Constructor</span></code> is called, the actor can be used to send and receive messages. It does not matter that the remote actor may not have been created yet due to asynchronicity.</p> <p>The destruction of actors is as unusual as their construction. Unlike construction, it is the same for managed and top-level actors. Avoiding <code class="docutils literal notranslate"><span class="pre">[ManualDealloc]</span></code> actors removes a lot of the complexity but there is still a process to understand. Actor destruction begins when an <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> message is sent. In <code class="docutils literal notranslate"><span class="pre">PMyManager</span></code>, this message is declared from child to parent. The actor calling <code class="docutils literal notranslate"><span class="pre">Send__delete__</span></code> is no longer connected to anything when the method returns. Future calls to <code class="docutils literal notranslate"><span class="pre">Send</span></code> return an error and no future messages will be received. This is also the case for an actor that has run <code class="docutils literal notranslate"><span class="pre">Recv__delete__</span></code>; it is no longer connected to the other endpoint.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Since <code class="docutils literal notranslate"><span class="pre">Send__delete__</span></code> may release the final reference to itself, it cannot safely be a class instance method. Instead, unlike other <code class="docutils literal notranslate"><span class="pre">Send</span></code> methods, it’s a <code class="docutils literal notranslate"><span class="pre">static</span></code> class method and takes the actor as a parameter:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">IPCResult</span><span class="w"> </span><span class="nf">Send__delete__</span><span class="p">(</span><span class="n">PMyManagerChild</span><span class="o">*</span><span class="w"> </span><span class="n">aToDelete</span><span class="p">);</span> </pre> </div> </div> <p>Additionally, the <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> message tells IPDL to disconnect both the given actor <em>and all of its managed actors</em>. So it is really deleting the actor subtree, although <code class="docutils literal notranslate"><span class="pre">Recv__delete__</span></code> is only called for the actor it was sent to.</p> </div> <p>During the call to <code class="docutils literal notranslate"><span class="pre">Send__delete__</span></code>, or after the call to <code class="docutils literal notranslate"><span class="pre">Recv__delete__</span></code>, the actor’s <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> method is called. This method gives client code a chance to do any teardown that must happen in <cite>all</cite> circumstances were it is possible – both expected and unexpected. This means that <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> will also be called when, for example, IPDL detects that the other endpoint has terminated unexpectedly, so it is releasing its reference to the actor, or because an ancestral manager (manager or manager’s manager…) received a <code class="docutils literal notranslate"><span class="pre">__delete__</span></code>. The only way for an actor to avoid <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> is for its process to crash first. <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> is always run after its actor is disconnected so it is pointless to try to send messages from it.</p> <p>Why use <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> instead of the actor’s destructor? <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code> gives a chance to clean up things that are only used for communication and therefore don’t need to live for however long the actor’s (reference-counted) object does. For example, you might have references to shared memory (Shmems) that are no longer valid. Or perhaps the actor can now release a cache of data that was only needed for processing messages. It is cleaner to deal with communication-related objects in <code class="docutils literal notranslate"><span class="pre">ActorDestroy</span></code>, where they become invalid, than to leave them in limbo until the destructor is run.</p> <p>Consider actors to be like normal reference-counted objects, but where IPDL holds a reference while the connection will or does exist. One common architecture has IPDL holding the <cite>only</cite> reference to an actor. This is common with actors created by sending constructor messages but the idea is available to any actor. That only reference is then released when the <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> message is sent or received.</p> <p>The dual of IPDL holding the only reference is to have client code hold the only reference. A common pattern to achieve this has been to override the actor’s <code class="docutils literal notranslate"><span class="pre">AddRef</span></code> to have it send <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> only when it’s count is down to one reference (which must be IPDL if <code class="docutils literal notranslate"><span class="pre">actor.CanSend()</span></code> is true). A better approach would be to create a reference-counted delegate for your actor that can send <code class="docutils literal notranslate"><span class="pre">__delete__</span></code> from its destructor. IPDL does not guarantee that it will not hold more than one reference to your actor.</p> </section> </section> <section id="top-level-actors"><span id="id5"></span> <h2>Top Level Actors<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#top-level-actors" title="Link to this heading">¶</a></h2> <p>Recall that top level actors are actors that have no manager. They are at the root of every actor tree. There are two settings in which we use top-level actors that differ pretty dramatically. The first type are top-level actors that are created and maintained in a way that resembles managed actors, but with some important differences we will cover in this section. The second type of top-level actors are the very first actors in a new process – these actors are created through different means and closing them (usually) terminates the process. The <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://phabricator.services.mozilla.com/D119038">new process example</a> demonstrates both of these. It is discussed in detail in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/processes.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#adding-a-new-type-of-process"><span class="std std-ref">Adding a New Type of Process</span></a>.</p> <section id="value-of-top-level-actors"> <h3>Value of Top Level Actors<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#value-of-top-level-actors" title="Link to this heading">¶</a></h3> <p>Top-level actors are harder to create and destroy than normal actors. They used to be more heavyweight than managed actors but this has recently been dramatically reduced.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Top-level actors previously required a dedicated <em>message channel</em>, which are limited OS resources. This is no longer the case – message channels are now shared by actors that connect the same two processes. This <em>message interleaving</em> can affect message delivery latency but profiling suggests that the change was basically inconsequential.</p> </div> <p>So why use a new top level actor?</p> <ul class="simple"> <li><p>The most dramatic property distinguishing top-level actors is the ability to <em>bind</em> to whatever <code class="docutils literal notranslate"><span class="pre">EventTarget</span></code> they choose. This means that any thread that runs a <code class="docutils literal notranslate"><span class="pre">MessageLoop</span></code> can use the event target for that loop as the place to send incoming messages. In other words, <code class="docutils literal notranslate"><span class="pre">Recv</span></code> methods would be run by that message loop, on that thread. The IPDL apparatus will asynchronously dispatch messages to these event targets, meaning that multiple threads can be handling incoming messages at the same time. The <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#pbackground">PBackground</a> approach was born of a desire to make it easier to exploit this, although it has some complications, detailed in that section, that limit its value.</p></li> <li><p>Top level actors suggest modularity. Actor protocols are tough to debug, as is just about anything that spans process boundaries. Modularity can give other developers a clue as to what they need to know (and what they don’t) when reading an actor’s code. The alternative is proverbial <em>dumpster classes</em> that are as critical to operations (because they do so much) as they are difficult to learn (because they do so much).</p></li> <li><p>Top level actors are required to connect two processes, regardless of whether the actors are the first in the process or not. As said above, the first actor is created through special means but other actors are created through messages. In Gecko, apart from the launcher and main processes, all new processes X are created with their first actor being between X and the main process. To create a connection between X and, say, a content process, the main process has to send connected <code class="docutils literal notranslate"><span class="pre">Endpoints</span></code> to X and to the content process, which in turn use those endpoints to create new top level actors that form an actor pair. This is discussed at length in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/processes.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#connecting-with-other-processes"><span class="std std-ref">Connecting With Other Processes</span></a>.</p></li> </ul> <p>Top-level actors are not as frictionless as desired but they are probably under-utilized relative to their power. In cases where it is supported, <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> is sometimes a simpler alternative to achieve the same goals.</p> </section> <section id="creating-top-level-actors-from-other-actors"> <h3>Creating Top Level Actors From Other Actors<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#creating-top-level-actors-from-other-actors" title="Link to this heading">¶</a></h3> <p>The most common way to create new top level actors is by creating a pair of connected Endpoints and sending one to the other actor. This is done exactly the way it sounds. For example:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="kt">bool</span><span class="w"> </span><span class="nf">MyPreexistingActorParent::MakeMyActor</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">Endpoint</span><span class="o"><</span><span class="n">PMyActorParent</span><span class="o">></span><span class="w"> </span><span class="n">parentEnd</span><span class="p">;</span> <span class="w"> </span><span class="n">Endpoint</span><span class="o"><</span><span class="n">PMyActorChild</span><span class="o">></span><span class="w"> </span><span class="n">childEnd</span><span class="p">;</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">NS_WARN_IF</span><span class="p">(</span><span class="n">NS_FAILED</span><span class="p">(</span><span class="n">PMyActor</span><span class="o">::</span><span class="n">CreateEndpoints</span><span class="p">(</span><span class="o">&</span><span class="n">parentEnd</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">childEnd</span><span class="p">))))</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// ... handle failure ...</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="n">RefPtr</span><span class="o"><</span><span class="n">MyActorParent</span><span class="o">></span><span class="w"> </span><span class="n">parent</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">MyActorParent</span><span class="p">;</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">parentEnd</span><span class="p">.</span><span class="n">Bind</span><span class="p">(</span><span class="n">parent</span><span class="p">))</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// ... handle failure ...</span> <span class="w"> </span><span class="k">delete</span><span class="w"> </span><span class="n">parent</span><span class="p">;</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="c1">// Do this second so we skip child if parent failed to connect properly.</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">SendCreateMyActorChild</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">childEnd</span><span class="p">)))</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// ... assume an IPDL error will destroy parent. Handle failure beyond that ...</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">true</span><span class="p">;</span> <span class="p">}</span> </pre> </div> </div> <p>Here <code class="docutils literal notranslate"><span class="pre">MyPreexistingActorParent</span></code> is used to send a child endpoint for the new top level actor to <code class="docutils literal notranslate"><span class="pre">MyPreexistingActorChild</span></code>, after it hooks up the parent end. In this example, we bind our new actor to the same thread we are running on – which must be the same thread <code class="docutils literal notranslate"><span class="pre">MyPreexistingActorParent</span></code> is bound to since we are sending <code class="docutils literal notranslate"><span class="pre">CreateMyActorChild</span></code> from it. We could have bound on a different thread.</p> <p>At this point, messages can be sent on the parent. Eventually, it will start receiving them as well.</p> <p><code class="docutils literal notranslate"><span class="pre">MyPreexistingActorChild</span></code> still has to receive the create message. The code for that handler is pretty similar:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="n">IPCResult</span><span class="w"> </span><span class="nf">MyPreexistingActorChild::RecvCreateMyActorChild</span><span class="p">(</span><span class="n">Endpoint</span><span class="o"><</span><span class="n">PMyActorChild</span><span class="o">>&&</span><span class="w"> </span><span class="n">childEnd</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">RefPtr</span><span class="o"><</span><span class="n">MyActorChild</span><span class="o">></span><span class="w"> </span><span class="n">child</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">MyActorChild</span><span class="p">;</span> <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">childEnd</span><span class="p">.</span><span class="n">Bind</span><span class="p">(</span><span class="n">child</span><span class="p">))</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// ... handle failure and return ok, assuming a related IPDL error will alert the other side to failure ...</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">IPC_OK</span><span class="p">();</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">IPC_OK</span><span class="p">();</span> <span class="p">}</span> </pre> </div> </div> <p>Like the parent, the child is ready to send as soon as <code class="docutils literal notranslate"><span class="pre">Bind</span></code> is complete. It will start receiving messages soon afterward on the event target for the thread on which it is bound.</p> </section> <section id="creating-first-top-level-actors"> <h3>Creating First Top Level Actors<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#creating-first-top-level-actors" title="Link to this heading">¶</a></h3> <p>The first actor in a process is an advanced topic that is covered in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/processes.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#adding-a-new-type-of-process"><span class="std std-ref">the documentation for adding a new process</span></a>.</p> </section> </section> <section id="pbackground"> <h2>PBackground<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#pbackground" title="Link to this heading">¶</a></h2> <p>Developed as a convenient alternative to top level actors, <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> is an IPDL protocol whose managees choose their worker threads in the child process and share a thread dedicated solely to them in the parent process. When an actor (parent or child) should run without hogging the main thread, making that actor a managee of <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> (aka a <em>background actor</em>) is an option.</p> <div class="admonition warning"> <p class="admonition-title">Warning</p> <p>Background actors can be difficult to use correctly, as spelled out in this section. It is recommended that other options – namely, top-level actors – be adopted instead.</p> </div> <p>Background actors can only be used in limited circumstances:</p> <ul class="simple"> <li><p><code class="docutils literal notranslate"><span class="pre">PBackground</span></code> only supports the following process connections (where ordering is parent <-> child): main <-> main, main <-> content, main <-> socket and socket <-> content.</p></li> </ul> <div class="admonition important"> <p class="admonition-title">Important</p> <p>Socket process <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> actor support was added after the other options. It has some rough edges that aren’t easy to anticipate. In the future, their support may be broken out into a different actor or removed altogether. You are strongly encouraged to use new <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#top-level-actors">Top Level Actors</a> instead of <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> actor when communicating with socket process worker threads.</p> </div> <ul class="simple"> <li><p>Background actor creation is always initiated by the child. Of course, a request to create one can be sent to the child by any other means.</p></li> <li><p>All parent background actors run in the same thread. This thread is dedicated to serving as the worker for parent background actors. While it has no other functions, it should remain responsive to all connected background actors. For this reason, it is a bad idea to conduct long operations in parent background actors. For such cases, create a top level actor and an independent thread on the parent side instead.</p></li> <li><p>Background actors are currently <em>not</em> reference-counted. IPDL’s ownership has to be carefully respected and the (de-)allocators for the new actors have to be defined. See <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-old-ways">The Old Ways</a> for details.</p></li> </ul> <p>A hypothetical layout of <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> threads, demonstrating some of the process-type limitations, is shown in the diagram below.</p> <figure class="align-center" id="id10"> <pre class="mermaid"> flowchart LR subgraph content #1 direction TB c1tm[main] c1t1[worker #1] c1t2[worker #2] c1t3[worker #3] end subgraph content #2 direction TB c2tm[main] c2t1[worker #1] c2t2[worker #2] end subgraph socket direction TB stm[main] st1[background parent /\nworker #1] st2[worker #2] end subgraph main direction TB mtm[main] mt1[background parent] end %% PBackground connections c1tm --> mt1 c1t1 --> mt1 c1t2 --> mt1 c1t3 --> mt1 c1t3 --> st1 c2t1 --> st1 c2t1 --> mt1 c2t2 --> mt1 c2tm --> st1 stm --> mt1 st1 --> mt1 st2 --> mt1 </pre> <figcaption> <p><span class="caption-text">Hypothetical <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> thread setup. Arrow direction indicates child-to-parent <code class="docutils literal notranslate"><span class="pre">PBackground</span></code>-managee relationships. Parents always share a thread and may be connected to multiple processes. Child threads can be any thread, including main.</span><a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#id10" title="Link to this image">¶</a></p> </figcaption> </figure> <p>Creating background actors is done a bit differently than normal managees. The new managed type and constructor are still added to <code class="docutils literal notranslate"><span class="pre">PBackground.ipdl</span></code> as with normal managees but, instead of <code class="docutils literal notranslate"><span class="pre">new</span></code>-ing the child actor and then passing it in a <code class="docutils literal notranslate"><span class="pre">SendFooConstructor</span></code> call, background actors issue the send call to the <code class="docutils literal notranslate"><span class="pre">BackgroundChild</span></code> manager, which returns the new child:</p> <div class="highlight-cpp notranslate"> <div class="highlight"> <pre><span></span><span class="c1">// Bind our new PMyBackgroundActorChild to the current thread.</span> <span class="n">PBackgroundChild</span><span class="o">*</span><span class="w"> </span><span class="n">bc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">BackgroundChild</span><span class="o">::</span><span class="n">GetOrCreateForCurrentThread</span><span class="p">();</span> <span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">bc</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span> <span class="p">}</span> <span class="n">PMyBackgroundActorChild</span><span class="o">*</span><span class="w"> </span><span class="n">pmyBac</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bac</span><span class="o">-></span><span class="n">SendMyBackgroundActor</span><span class="p">(</span><span class="n">constructorParameters</span><span class="p">);</span> <span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">pmyBac</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span> <span class="p">}</span> <span class="k">auto</span><span class="w"> </span><span class="n">myBac</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">static_cast</span><span class="o"><</span><span class="n">MyBackgroundActorChild</span><span class="o">*></span><span class="p">(</span><span class="n">pmyBac</span><span class="p">);</span> </pre> </div> </div> <div class="admonition note"> <p class="admonition-title">Note</p> <p><code class="docutils literal notranslate"><span class="pre">PBackgroundParent</span></code> still needs a <code class="docutils literal notranslate"><span class="pre">RecvMyBackgroundActorConstructor</span></code> handler, as usual. This must be done in the <code class="docutils literal notranslate"><span class="pre">ParentImpl</span></code> class. <code class="docutils literal notranslate"><span class="pre">ParentImpl</span></code> is the non-standard name used for the implementation of <code class="docutils literal notranslate"><span class="pre">PBackgroundParent</span></code>.</p> </div> <p>To summarize, <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> attempts to simplify a common desire in Gecko: to run tasks that communicate between the main and content processes but avoid having much to do with the main thread of either. Unfortunately, it can be complicated to use correctly and has missed on some favorable IPDL improvements, like reference counting. While top level actors are always a complete option for independent jobs that need a lot of resources, <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> offers a compromise for some cases.</p> </section> <section id="ipdl-best-practices"> <h2>IPDL Best Practices<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#ipdl-best-practices" title="Link to this heading">¶</a></h2> <p>IPC performance is affected by a lot of factors. Many of them are out of our control, like the influence of the system thread scheduler on latency or messages whose travel internally requires multiple legs for security reasons. On the other hand, some things we can and should control for:</p> <ul class="simple"> <li><p>Messages incur inherent performance overhead for a number of reasons: IPDL internal thread latency (e.g. the I/O thread), parameter (de-)serialization, etc. While not usually dramatic, this cost can add up. What’s more, each message generates a fair amount of C++ code. For these reasons, it is wise to reduce the number of messages being sent as far as is reasonable. This can be as simple as consolidating two asynchronous messages that are always in succession. Or it can be more complex, like consolidating two somewhat-overlapping messages by merging their parameter lists and marking parameters that may not be needed as optional. It is easy to go too far down this path but careful message optimization can show big gains.</p></li> <li><p>Even <code class="docutils literal notranslate"><span class="pre">[moveonly]</span></code> parameters are “copied” in the sense that they are serialized. The pipes that transmit the data are limited in size and require allocation. So understand that the performance of your transmission will be inversely proportional to the size of your content. Filter out data you won’t need. For complex reasons related to Linux pipe write atomicity, it is highly desirable to keep message sizes below 4K (including a small amount for message metadata).</p></li> <li><p>On the flip side, very large messages are not permitted by IPDL and will result in a runtime error. The limit is currently 256M but message failures frequently arise even with slightly smaller messages.</p></li> <li><p>Parameters to messages are C++ types and therefore can be very complex in the sense that they generally represent a tree (or graph) of objects. If this tree has a lot of objects in it, and each of them is serialized by <code class="docutils literal notranslate"><span class="pre">ParamTraits</span></code>, then we will find that serialization is allocating and constructing a lot of objects, which will stress the allocator and cause memory fragmentation. Avoid this by using larger objects or by sharing this kind of data through careful use of shared memory.</p></li> <li><p>As it is with everything, concurrency is critical to the performance of IPDL. For actors, this mostly manifests in the choice of bound thread. While adding a managed actor to an existing actor tree may be a quick implementation, this new actor will be bound to the same thread as the old one. This contention may be undesirable. Other times it may be necessary since message handlers may need to use data that isn’t thread safe or may need a guarantee that the two actors’ messages are received in order. Plan up front for your actor hierarchy and its thread model. Recognize when you are better off with a new top level actor or <code class="docutils literal notranslate"><span class="pre">PBackground</span></code> managee that facilitates processing messages simultaneously.</p></li> <li><p>Remember that latency will slow your entire thread, including any other actors/messages on that thread. If you have messages that will need a long time to be processed but can run concurrently then they should use actors that run on a separate thread.</p></li> <li><p>Top-level actors decide a lot of properties for their managees. Probably the most important are the process layout of the actor (including which process is “Parent” and which is “Child”) and the thread. Every top-level actor should clearly document this, ideally in their .ipdl file.</p></li> </ul> </section> <section id="the-old-ways"> <h2>The Old Ways<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-old-ways" title="Link to this heading">¶</a></h2> <p>TODO:</p> </section> <section id="the-fud"> <h2>The FUD<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-fud" title="Link to this heading">¶</a></h2> <p>TODO:</p> </section> <section id="the-rest"> <h2>The Rest<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#the-rest" title="Link to this heading">¶</a></h2> <section id="nested-messages"> <h3>Nested messages<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#nested-messages" title="Link to this heading">¶</a></h3> <p>The <code class="docutils literal notranslate"><span class="pre">Nested</span></code> message annotations indicate the nesting type of the message. They attempt to process messages in the nested order of the “conversation thread”, as found in e.g. a mailing-list client. This is an advanced concept that should be considered to be discouraged, legacy functionality. Essentially, <code class="docutils literal notranslate"><span class="pre">Nested</span></code> messages can make other <code class="docutils literal notranslate"><span class="pre">sync</span></code> messages break the policy of blocking their thread – nested messages are allowed to be received while a sync messagee is waiting for a response. The rules for when a nested message can be handled are somewhat complex but they try to safely allow a <code class="docutils literal notranslate"><span class="pre">sync</span></code> message <code class="docutils literal notranslate"><span class="pre">M</span></code> to handle and respond to some special (nested) messages that may be needed for the other endpoint to finish processing <code class="docutils literal notranslate"><span class="pre">M</span></code>. There is a <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/rev/077501b34cca91763ae04f4633a42fddd919fdbd/ipc/glue/MessageChannel.cpp%2354-118">comment in MessageChannel</a> with info on how the decision to handle nested messages is made. For sync nested messages, note that this implies a relay between the endpoints, which could dramatically affect their throughput.</p> <p>Declaring messages to nest requires an annotation on the actor and one on the message itself. The nesting annotations were listed in <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#defining-actors">Defining Actors</a> and <a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#declaring-ipdl-messages">Declaring IPDL Messages</a>. We repeat them here. The actor annotations specify the maximum priority level of messages in the actor. It is validated by the IPDL compiler. The annotations are:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[NestedUpTo=inside_sync]</span></code></p></td> <td><p>Indicates that an actor contains messages of priority [Nested=inside_sync] or lower.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[NestedUpTo=inside_cpow]</span></code></p></td> <td><p>Indicates that an actor contains messages of priority [Nested=inside_cpow] or lower.</p></td> </tr> </tbody> </table> <div class="admonition note"> <p class="admonition-title">Note</p> <p>The order of the nesting priorities is: (no nesting priority) < <code class="docutils literal notranslate"><span class="pre">inside_sync</span></code> < <code class="docutils literal notranslate"><span class="pre">inside_cpow</span></code>.</p> </div> <p>The message annotations are:</p> <table class="docutils align-default"> <tbody> <tr class="row-odd"> <td><p><code class="docutils literal notranslate"><span class="pre">[Nested=inside_sync]</span></code></p></td> <td><p>Indicates that the message can be handled while waiting for lower-priority, or in-message-thread, sync responses.</p></td> </tr> <tr class="row-even"> <td><p><code class="docutils literal notranslate"><span class="pre">[Nested=inside_cpow]</span></code></p></td> <td><p>Indicates that the message can be handled while waiting for lower-priority, or in-message-thread, sync responses. Cannot be sent by the parent actor.</p></td> </tr> </tbody> </table> <div class="admonition note"> <p class="admonition-title">Note</p> <p><code class="docutils literal notranslate"><span class="pre">[Nested=inside_sync]</span></code> messages must be sync (this is enforced by the IPDL compiler) but <code class="docutils literal notranslate"><span class="pre">[Nested=inside_cpow]</span></code> may be async.</p> </div> <p>Nested messages are obviously only interesting when sent to an actor that is performing a synchronous wait. Therefore, we will assume we are in such a state. Say <code class="docutils literal notranslate"><span class="pre">actorX</span></code> is waiting for a sync reply from <code class="docutils literal notranslate"><span class="pre">actorY</span></code> for message <code class="docutils literal notranslate"><span class="pre">m1</span></code> when <code class="docutils literal notranslate"><span class="pre">actorY</span></code> sends <code class="docutils literal notranslate"><span class="pre">actorX</span></code> a message <code class="docutils literal notranslate"><span class="pre">m2</span></code>. We distinguish two cases here: (1) when <code class="docutils literal notranslate"><span class="pre">m2</span></code> is sent while processing <code class="docutils literal notranslate"><span class="pre">m1</span></code> (so <code class="docutils literal notranslate"><span class="pre">m2</span></code> is sent by the <code class="docutils literal notranslate"><span class="pre">RecvM1()</span></code> method – this is what we mean when we say “nested”) and (2) when <code class="docutils literal notranslate"><span class="pre">m2</span></code> is unrelated to <code class="docutils literal notranslate"><span class="pre">m1</span></code>. Case (2) is easy; <code class="docutils literal notranslate"><span class="pre">m2</span></code> is only dispatched while <code class="docutils literal notranslate"><span class="pre">m1</span></code> waits if <code class="docutils literal notranslate"><span class="pre">priority(m2)</span> <span class="pre">></span> <span class="pre">priority(m1)</span> <span class="pre">></span> <span class="pre">(no</span> <span class="pre">priority)</span></code> and the message is being received by the parent, or if <code class="docutils literal notranslate"><span class="pre">priority(m2)</span> <span class="pre">>=</span> <span class="pre">priority(m1)</span> <span class="pre">></span> <span class="pre">(no</span> <span class="pre">priority)</span></code> and the message is being received by the child. Case (1) is less straightforward.</p> <p>To analyze case (1), we again distinguish the two possible ways we can end up in the nested case: (A) <code class="docutils literal notranslate"><span class="pre">m1</span></code> is sent by the parent to the child and <code class="docutils literal notranslate"><span class="pre">m2</span></code> is sent by the child to the parent, or (B) where the directions are reversed. The following tables explain what happens in all cases:</p> <table class="docutils align-center" id="id11"> <caption> <span class="caption-text">Case (A): Child sends message to a parent that is awaiting a sync response</span><a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#id11" title="Link to this table">¶</a> </caption> <thead> <tr class="row-odd"> <th class="head"><p>sync <code class="docutils literal notranslate"><span class="pre">m1</span></code> type (from parent)</p></th> <th class="head"><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> type (from child)</p></th> <th class="head"><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> handled or rejected</p></th> </tr> </thead> <tbody> <tr class="row-even"> <td><p>sync (no priority)</p></td> <td><p>*</p></td> <td><p>IPDL compiler error: parent cannot send sync (no priority)</p></td> </tr> <tr class="row-odd"> <td><p>sync inside_sync</p></td> <td><p>async (no priority)</p></td> <td><p><strike> <code class="docutils literal notranslate"><span class="pre">m2</span></code> delayed until after <code class="docutils literal notranslate"><span class="pre">m1</span></code> completes </strike> <br> Currently <code class="docutils literal notranslate"><span class="pre">m2</span></code> is handled during the sync wait (bug?)</p></td> </tr> <tr class="row-even"> <td><p>sync inside_sync</p></td> <td><p>sync (no priority)</p></td> <td><p><strike> <code class="docutils literal notranslate"><span class="pre">m2</span></code> send fails: lower priority than <code class="docutils literal notranslate"><span class="pre">m1</span></code> </strike> <br> Currently <code class="docutils literal notranslate"><span class="pre">m2</span></code> is handled during the sync wait (bug?)</p></td> </tr> <tr class="row-odd"> <td><p>sync inside_sync</p></td> <td><p>sync inside_sync</p></td> <td><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> handled during <code class="docutils literal notranslate"><span class="pre">m1</span></code> sync wait: same message thread and same priority</p></td> </tr> <tr class="row-even"> <td><p>sync inside_sync</p></td> <td><p>async inside_cpow</p></td> <td><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> handled during <code class="docutils literal notranslate"><span class="pre">m1</span></code> sync wait: higher priority</p></td> </tr> <tr class="row-odd"> <td><p>sync inside_sync</p></td> <td><p>sync inside_cpow</p></td> <td><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> handled during <code class="docutils literal notranslate"><span class="pre">m1</span></code> sync wait: higher priority</p></td> </tr> <tr class="row-even"> <td><p>sync inside_cpow</p></td> <td><p>*</p></td> <td><p>IPDL compiler error: parent cannot use inside_cpow priority</p></td> </tr> </tbody> </table> <table class="docutils align-center" id="id12"> <caption> <span class="caption-text">Case (B): Parent sends message to a child that is awaiting a sync response</span><a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#id12" title="Link to this table">¶</a> </caption> <thead> <tr class="row-odd"> <th class="head"><p>sync <code class="docutils literal notranslate"><span class="pre">m1</span></code> type (from child)</p></th> <th class="head"><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> type (from parent)</p></th> <th class="head"><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> handled or rejected</p></th> </tr> </thead> <tbody> <tr class="row-even"> <td><p>*</p></td> <td><p>async (no priority)</p></td> <td><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> delayed until after <code class="docutils literal notranslate"><span class="pre">m1</span></code> completes</p></td> </tr> <tr class="row-odd"> <td><p>*</p></td> <td><p>sync (no priority)</p></td> <td><p>IPDL compiler error: parent cannot send sync (no priority)</p></td> </tr> <tr class="row-even"> <td><p>sync (no priority)</p></td> <td><p>sync inside_sync</p></td> <td><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> send fails: no-priority sync messages cannot handle incoming messages during wait</p></td> </tr> <tr class="row-odd"> <td><p>sync inside_sync</p></td> <td><p>sync inside_sync</p></td> <td><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> handled during <code class="docutils literal notranslate"><span class="pre">m1</span></code> sync wait: same message thread and same priority</p></td> </tr> <tr class="row-even"> <td><p>sync inside_cpow</p></td> <td><p>sync inside_sync</p></td> <td><p><code class="docutils literal notranslate"><span class="pre">m2</span></code> send fails: lower priority than <code class="docutils literal notranslate"><span class="pre">m1</span></code></p></td> </tr> <tr class="row-odd"> <td><p>*</p></td> <td><p>async inside_cpow</p></td> <td><p>IPDL compiler error: parent cannot use inside_cpow priority</p></td> </tr> <tr class="row-even"> <td><p>*</p></td> <td><p>sync inside_cpow</p></td> <td><p>IPDL compiler error: parent cannot use inside_cpow priority</p></td> </tr> </tbody> </table> <p>We haven’t seen rule #2 from the <a class="reference external" href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://searchfox.org/mozilla-central/rev/077501b34cca91763ae04f4633a42fddd919fdbd/ipc/glue/MessageChannel.cpp%2354-118">comment in MessageChannel</a> in action but, as the comment mentions, it is needed to break deadlocks in cases where both the parent and child are initiating message-threads simultaneously. It accomplishes this by favoring the parent’s sent messages over the child’s when deciding which message-thread to pursue first (and blocks the other until the first completes). Since this distinction is entirely thread-timing based, client code needs only to be aware that IPDL internals will not deadlock because of this type of race, and that this protection is limited to a single actor tree – the parent/child messages are only well-ordered when under the same top-level actor so simultaneous sync messages across trees are still capable of deadlock.</p> <p>Clearly, tight control over these types of protocols is required to predict how they will coordinate within themselves and with the rest of the application objects. Control flow, and hence state, can be very difficult to predict and are just as hard to maintain. This is one of the key reasons why we have stressed that message priorities should be avoided whenever possible.</p> </section> <section id="message-logging"><span id="id6"></span> <h3>Message Logging<a class="headerlink" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/ipdl.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#message-logging" title="Link to this heading">¶</a></h3> <p>The environment variable <code class="docutils literal notranslate"><span class="pre">MOZ_IPC_MESSAGE_LOG</span></code> controls the logging of IPC messages. It logs details about the transmission and reception of messages. This isn’t controlled by <code class="docutils literal notranslate"><span class="pre">MOZ_LOG</span></code> – it is a separate system. Set this variable to <code class="docutils literal notranslate"><span class="pre">1</span></code> to log information on all IPDL messages, or specify a comma-separated list of protocols to log. If the <code class="docutils literal notranslate"><span class="pre">Child</span></code> or <code class="docutils literal notranslate"><span class="pre">Parent</span></code> suffix is given, then only activity on the given side is logged; otherwise, both sides are logged. All protocol names must include the <code class="docutils literal notranslate"><span class="pre">P</span></code> prefix.</p> <p>For example:</p> <div class="highlight-default notranslate"> <div class="highlight"> <pre><span></span><span class="n">MOZ_IPC_MESSAGE_LOG</span><span class="o">=</span><span class="s2">"PMyManagerChild,PMyManaged"</span> </pre> </div> </div> <p>This requests logging of child-side activity on <code class="docutils literal notranslate"><span class="pre">PMyManager</span></code>, and both parent- and child-side activity on <code class="docutils literal notranslate"><span class="pre">PMyManaged</span></code>.</p> <p><a class="reference internal" href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/processes.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB#debugging-with-ipdl-logging"><span class="std std-ref">Debugging with IPDL Logging</span></a> has an example where IPDL logging is useful in tracking down a bug.</p> </section> </section> </section> </div> </div> <footer> <div class="rst-footer-buttons" role="navigation" aria-label="Footer"><a href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/index.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB" class="btn btn-neutral float-left" title="Processes, Threads and IPC" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> <a href="https://firefox--source--docs-mozilla-org.translate.goog/ipc/processes.html?_x_tr_sl=pl&_x_tr_tl=iw&_x_tr_hl=en-GB" class="btn btn-neutral float-right" title="Gecko Processes" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> </div> <hr> <div role="contentinfo"> <p></p> </div> Built with <a href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://www.sphinx-doc.org/">Sphinx</a> using a <a href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://translate.google.com/website?sl=pl&tl=iw&hl=en-GB&u=https://readthedocs.org">Read the Docs</a>. </footer> </div> </div> </section> </div> <script> jQuery(function () { SphinxRtdTheme.Navigation.enable(true); }); </script> <script>function gtElInit() {var lib = new google.translate.TranslateService();lib.translatePage('pl', 'iw', function () {});}</script> <script src="https://translate.google.com/translate_a/element.js?cb=gtElInit&hl=en-GB&client=wt" type="text/javascript"></script> </body> </html>