mozilla

Revision 636001 of B2G IPC internals

  • Revision slug: Mozilla/Firefox_OS/Security/B2G_IPC_internals
  • Revision title: B2G IPC internals
  • Revision id: 636001
  • Created:
  • Creator: ptheriault
  • Is current revision? No
  • Comment

Revision Content

This article will focus on the internal workings of the Inter-Process Communication (IPC) implementation in FirefoxOS (Boot2Gecko).
It is still in development and might change a lot along the way. The main purpose of this article is, to give a detailed insight of the internal working and implementaiton.
To read more about the security aspect of the IPC, please check out this article (TODO: create and link to other article). Any feedback or suggestion is greatly appreciated.

Architecture


In FirefoxOS we have a Multi-process Architecture, where the apps on the phone are running in a different process, which has the least amount of privileges. On a running system we have a single parent process called b2g. The b2g process has a child process called nuwa, this process will be used to fork the app processes. Whenever a new app is being started on the phone, b2g tells nuwa that we need a new process. By default,  child processes are run with a minimal set of privileges. For every action they want to perform (that needs more privileges), they need to go through the parent process (b2g). This is where the Inter-process Communication (IPC) comes into place. Each child has a connection, using an IPC channel, to the parent which will be used for their communication. The process layout is illustrated on the right.

Setup

Now that you have a rough overview of how everything is laid out, we will go into more detail on how this communication actually works.
We use Unix sockets, created with the socketpair system call, to send messages across the process boundary. For writing and reading, the system calls sendmsg and recvmsg are being used. Each process has its own dedicated thread that handles the socket operations, it is called IOLoop. Each IOLoop thread has its own outgoing message queue, which is used by the main thread to send a new message across the channel.

IOLoop

An IOLoop thread is created for the parent during b2g startup, and for each child process after nuwa forks.

Parent

In the parent process (b2g) the IOLoop is created very early on, more precisely it happens in the NS_InitXPCOM2 function. This is the code snippet that actually initiates the thread start:

...
scoped_ptr<BrowserProcessSubThread> ioThread(
    new BrowserProcessSubThread(BrowserProcessSubThread::IO));
...
ioThread->StartWithOptions(options)
...

ioThread is an instance of BrowserProcessSubThread which inherits from base::Thread, itself a subclass of PlatformThread::Delegate.

StartWithOptions is actually defined in base::Thread, the call will lead to a couple of more calls which will eventually end up at pthread_create. The function started in the new thread is ThreadFunc. ioThread object is passed along the calls and ioThread->ThreadMain() is called in the new thread.

ThreadMain is now running in the IOLoop thread, it will call Init() of the current instance and also creates a MessageLoop instance and call the Run() method. We will <come any="" back="" is="" it="" later="" not="" of="" p="" part="" since="" startup="" that="" the="" thread="" to=""> </come>revisit this part later on, since it is not involved further in thread startup.

...
// The message loop for this thread.
MessageLoop message_loop(startup_data_->options.message_loop_type);
...
// Let the thread do extra initialization.
// Let's do this before signaling we are started.
Init();
...
message_loop.Run();
...

Child

For the child IOLoop thread spawn, we have to look at the nuwa process as a child of b2g, but also at the forked processes of nuwa.

Exactly how b2g spawns nuwa will be covered later; for now we assume that the nuwa process already exists. Once nuwa is created, we eventually reach the XRE_InitChildProcess function. This function is responsible for creating the IOLoop thread at this line:

process = new ContentProcess(parentHandle);

In the ContentProcess constructor, the ProcessChild constructor is called, which leads to a call of the ChildProcess constructor. The important part to note here is, that the ChildProcess constructor gets passed a new instance of IOThreadChild. Within the constructor, the Run() is called on the passed IOThreadChild object:

ChildProcess::ChildProcess(ChildThread* child_thread)
    : child_thread_(child_thread),
    ...
{
    ...
        child_thread_->Run();
}

From there, the StartWithOptions function is called. At this point, it follows the same code path as for the main IOLoop startup the only exception is, that it is a IOThreadChild instance and not a BrowserProcessSubThread (see the b2g process illustration above for reference).

Below is an illustration of the IOLoop thread spawn in the  nuwa process :

This is the case for the original nuwa process. All future children will be forked from nuwa, and since fork only copies the thread it was called in to the new process, all threads so far would be lost.

We want to have all threads from nuwa (along with the IOLoop), in the forked process. In order to do that, pthread_create is not called directly, instead, the call is routed to __wrap_pthread_create which wraps the real pthread_create. The purpose of the wrapper function, is to maintain a static list of startup information for all created threads (sAllThreads). This list will be copied to the new process, the new process will then call RecreateThreads to restore all threads, based on the information maintained in the list.

Channel

In order to be able to send and receive messages, we have to create a channel between the parent and the child. This section covers the classes used for this - the actual setup between parent and child will be covered once we get to the process spawning part.

Here a short illustration of the call flow:

  1.  The part of this flow is the creation of an IPC::Channel instance (the process of creating the instance will be covered later on). This class has two important attributes:
    • channel_impl_ which is the actual implementation of the channel (platform specific)
    • listener_ this is used to pass incoming messages to
  2. The posix class for the channel_impl_ object can be found here (Channel::ChannelImpl). Channel::ChannelImpl has the following important attributes:
    • pipe_ the file descriptor of the pipe (created by socketpair) for the parent side
    • client_pipe_ the client end of the pipe
    • listener_ the object that receives the incoming messages
    • output_queue_ a queue where all outgoing messages are pushed to
  3. Channel::ChannelImpl has two overloaded constructor which can be used to create an object. One of them takes a file descriptor as the first argument which will be stored in pipe_. The more interesting constructor is the one which takes a channel_id (can also be empty). Both of them also take a Mode and a Listener* pointer as second and third argument. Mode just specifies if we are the server or the client. When the constructor with the channel_id is called, CreatePipe will be called from there. We have to distinguish two different cases from here:
    • Mode == MODE_SERVER: In this case, socketpair will be called. One end of the pipe will be stored in pipe_ the other in client_pipe_. If channel_id is not empty, we insert a new entry in a PipeMap where we associate client_pipe_ with the given channel_id.
    • Mode != MODE_SERVER: In this case, we call ChannelNameToClientFD, which looks inside the PipeMap for an entry with the given channel_id. The result will be stored in pipe_.
  4. After the object creation is completed, the Connect method can be called, this method will tell libevent to notify us whenever something has been written to pipe_ and is ready to be received.
  5. OnFileCanReadWithoutBlocking is the callback for this event. This function will then call a function to read the message from the file descriptor and then the message will be passed to the OnMessageReceived function inside the listener_ (this will be covered later).

Spawning

In the previous section, we learned how IOLoop is created and how a channel is created. Throughout the last sections, we made the assumption that a process has already been started. This section will cover how those processes actually get started and how they connect to the IPC::Channel. We will again, have to distinguish between the nuwa process and the children of nuwa.

At this point I would suggest reading the IPDL Tutorial, because from this point on we will reference to some of the classes generated from those IPDL files.

Nuwa

creating the process

Throughout the initialization phase of the b2g process, an instance of the singleton class PreallocatedProcessManagerImpl will be created. This instance is mainly accessed through a couple of static functions defined in the PreallocatedProcessManager class. The purpose of this manager is to keep track of pre-allocated processes, this will be explained in more detail in the #Preallocated section.

The implementation class has two important attributes:

  • mSpareProcesses which is an array that contains the preallocated processes (will be important later on)
  • mPreallocatedAppProcess which will be the nuwa process

This initialization happens inside the ContentParent::StartUp function, when executing the following code:

...
// Try to preallocate a process that we can transform into an app later.
PreallocatedProcessManager::AllocateAfterDelay();
...

This call will lead to the creation of the one and only instance of PreallocatedProcessManagerImpl is created (inside the PreallocatedProcessManagerImpl::Singleton function). Right after the constructor call, the Init function is invoked. Following the call flow from there, we will end up in Enable. Enable will then schedule the nuwa fork, with a 1 second delay (DEFAULT_ALLOCATE_DELAY), by calling ScheduleDelayedNuwaFork. This gives the b2g process enough time to finish its initialization.

As soon as the delay time has passed, the DelayedNuwaFork function is called inside the main thread. Inside the function, we will call ContentParent::RunNuwaProcess which returns a pointer to a ContentParent object, this object represents our nuwa process.

Inside the ContentParent constructor, a couple of interesting things happen.

The LaunchAndWaitForProcessHandle method will schedule a task inside the IOLoop thread. In the IOLoop thread, RunPerformAsyncLaunch is called. After a few calls, we will end up in the LaunchApp function. This is where the forking happens. After the fork, it will call execve in the child to re-execute itself.

connect to the channel

We covered the actual spawning, what's left is the part where the parent (b2g) and the child (nuwa) connect to the same IPC channel. We have two important calls for that on the parent side, one is made before the child was spawned, the other after the spawn. The first one is in the RunPerformAsynchLaunch function, before actually calling PerformAsynchLaunch (the position is marked with a 'x' in the above diagram), we call InitializeChannel this will call CreateChannel. At this point a new IPC::Channel object is created, so please checkout the #Channel section above.

The GeckoChildProcessHost object created inside the ContentParent constructor, serves as the listener_ inside the IPC::Channel object. So GeckoChildProcessHost will supply the OnMessageReceived function. There is nothing done there, it just saves all the incoming messages.

At this point we can consider the parent process to be connected to the channel. This was the first important call.

The second one is called as soon as LaunchAndWaitForProcessHandle returned (nuwa process is running at this point). Since the current OnMessageReceived handler doesn't do any good, we will have to assign a new listener_. In order to do that, this is being executed (mSubprocess is an instance of GeckoChildProcessHost which is created in ContentParent):

Open(mSubprocess->GetChannel(), mSubprocess->GetOwnedChildProcessHandle());

What happens now is a little complicated to explain just with text, so try to follow along, I will try to illustrate the process in the end, so you might want to follow the process again with the illustration.

ContentParent actually extends PContentParent (this class is generated from the *.ipdl files, I can't reference to any github or mxr location), which is defined in ./objdir-gecko/ipc/ipdl/PContentParent.cpp relative to the root directory of FirefoxOS. PContentParent has a member variable which will be important during the Open (defined in PContentParent.cpp) call.

MessageChannel takes a MessageListener object as the one and only argument. mChannel is created during the PContentParent construction and passes this as the MessageListener object to MessageChannel (ContentParent extends MessageListener shown below.

Open gets the IPC::Channel instance taken from mSubprocess (TODO: GetOwnedChildProcessHandle???) and calls Open on mChannel

auto PContentParent::Open(
        Channel::Transport* aTransport,
        ProcessHandle aOtherProcess,
        MessageLoop* aThread,
        mozilla::ipc::Side aSide) -> bool
{
    mOtherProcess = aOtherProcess;
    return (mChannel).Open(aTransport, aThread, aSide);
}

As a side note, Channel::Transport is a typedef of IPC::Channel. aThread and aSide are set to 0 and UnknownSide by default if not specified. Open inside of the MessageChannel class will create a ProcessLink, this is passed to the constructor which will set mChan inside the MessageLink class which ProcessLink inherits from.

After a instance of ProcessLink is created, we call Open on it. This sets the member variable mTransport (which represents the IPC::Channel). So mTransport is the IPC::Channel pointer we retrieved from mSubprocess

Since Connect has already been called when the IPC::Channel was created, we will schedule IOLoop to run OnTakeConnectedChannel. The channel state inside the MessageChannel object will be set to ChannelConnected and we also call set_listener on the IPC::Channel instance to let it know, that ProcessLink will handle incoming messages, that means OnMessageReceived inside ProcessLink is called. Those received messages will be passed to the MessageChannel and from there to the OnMessageReceived funciton inside the PContentParent class.

Now everything has been setup on the parent side. Let's get to the nuwa side.

After the fork, nuwa inherited all the open file descriptors from the parent b2g, one of them is its end of the pipe. Every child expects its end of the pipe to be file descriptor 3 (kClientChannelFd). In order to guarantee that file descriptor 3 will be the child's end of the pipe, we call ShuffleFileDescriptors, this function will dup the child end of the pipe to 3. It also makes sure that in case 3 is a file descriptor needed by the child, that it will be remapped to the next available.

After the file descriptors have been remapped, we call CloseSuperfluousFds to close all the ones that nuwa doesn't need. When everything is done, the child will call execve to re-execute itself.

From here please have a look at the #Child section, the actual channel connection will happen inside the ThreadMain function inside the IOLoop thread. ThreadMain will call Init defined in ChildThread. Inside this function, we will create a new IPC::Channel object, and you can refer to the #Channel section from here. You will have to consider the part Mode != MODE_SERVER, therefore ChannelNameToClientFD will be called, which returns our magic file descriptor 3 (remember the child end of the pipe is mapped to this fd).

So now, we have a connection to the channel, what is left is to set the correct listener for the incoming messages. To do so, the Init funciton inside ContentProcess is called. From there it will call Open in the PContentChild class, this will lead to the same call flow as for the parent in the above diagram. The only exception we have is that these calls originate from ContentChild which inherits from PContentChild.

Preallocated

creating the process

A Preallocated process is a process fork()ed from nuwa which b2g keeps around, to turn it later into a app process. So at some point in time, b2g tells the preallocated process to turn into the game app that has been started on the phone. The process will then be assigned to the privileges of the app and the user will be able to do all the fancy stuff the app can do. As soon as a Preallocated process hasn been turned into an app, b2g will tell nuwa to create a new Preallocated process. So how does b2g tell nuwa to create a new Preallocated process? (at this point we have an active channel connection between b2g and nuwa)

For initiating the fork, b2g sends a message through the IPC channel and nuwa sends one back once it created the new process, the message contains the PID of the new process. On the right is a little illustration of the message flow.

Sending the initial message is initiated inside the NuwaFork function. Remeber the mPreallocatedAppProcess is an instance of ContentParent and the invoked SendNuwaFork function is actually implemented inside PContentParent.

As soon as the child receives this messages, it will call RecvNuwaFork which is defined in ContentChild. Following the calls from there, we will end up in ForkIPCProcess.

From there we call PrepareProtoSockets which calls socketpair to create a new pipe for the new child and the parent.
It is also where fork is called and our new process is born. After the fork we will call AddNewProcess inside nuwa. AddNewIPCProcess will then be responsible for initiating the second message. The message contains the parent side file descriptor for the pipe as well as the PID of the new process.

On the b2g side the RecvAddNewProcess will handle the message. It will create a new ContentParent instance. This time we call the second ContentParent constructor. It will create the ContentParent instance based on the already existing one and with the information of the new process. This also leads to a new instance in our static sContentParents list. This basically means that we have a ContentParent instance for each process that is running.

There is also a check in place which makes sure that only the nuwa process actually sends Msg_AddNewProcess:

...
if (!IsNuwaProcess()) {
...

IsNuwaProcess checks a member variable of ContentParent wether or not it is nuwa who sent the message. This member variable can only be set from the parent side and it does this during the creation of the ContentParent for the nuwa process.

After initialization is finished, RecvAddNewProcess will then call PublishSpareProcess to add the process to the managers list, which will keep track of all existing Preallocated processes. Whenever a Preallocated process will be turned into a app process, it will be removed from that spare processes list. Here an illustration of the process:

connect to the channel

TODO: write it

Revision Source

<div class="note">
 <p>This article will focus on the internal workings of the Inter-Process Communication (IPC) implementation in FirefoxOS (Boot2Gecko).<br />
  It is still in development and might change a lot along the way. The main purpose of this article is, to give a detailed insight of the internal working and implementaiton.<br />
  To read more about the security aspect of the IPC, please check out this article (TODO: create and link to other article). Any feedback or suggestion is greatly appreciated.</p>
</div>
<h2 id="Architecture">Architecture</h2>
<p><img alt="" src="https://mdn.mozillademos.org/files/8103/illu1_arch.png" style="width: 300px; height: 283px; float: right; border-width: 1px; border-style: solid;" /><br />
 In FirefoxOS we have a Multi-process Architecture, where the apps on the phone are running in a different process, which has the least amount of privileges. On a running system we have a single parent process called <em>b2g</em>. The <em>b2g</em> process has a child process called <em>nuwa</em>, this process will be used to fork the app processes. Whenever a new app is being started on the phone, <em>b2g</em> tells <em>nuwa</em> that we need a new process. By default,&nbsp; child processes are run with a minimal set of privileges. For every action they want to perform (that needs more privileges), they need to go through the parent process (b2g). This is where the Inter-process Communication (IPC) comes into place. Each child has a connection, using an IPC channel, to the parent which will be used for their communication. The process layout is illustrated on the right.</p>
<h2 id="Setup">Setup</h2>
<p>Now that you have a rough overview of how everything is laid out, we will go into more detail on how this communication actually works.<br />
 We use Unix sockets, created with the <strong>socketpair</strong> system call, to send messages across the process boundary. For writing and reading, the system calls <strong>sendmsg</strong> and <strong>recvmsg</strong> are being used. Each process has its own dedicated thread that handles the socket operations, it is called <em>IOLoop</em>. Each <em>IOLoop</em> thread has its own outgoing message queue, which is used by the main thread to send a new message across the channel.</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/8105/illu2_ioloop.png" style="width: 700px; height: 203px;" /></p>
<h3 id="IOLoop">IOLoop</h3>
<p>An <em>IOLoop</em> thread is created for the parent during <em>b2g</em> startup, and for each child process after <em>nuwa</em> forks.</p>
<h4 id="Parent"><strong>Parent</strong></h4>
<p>In the parent process (b2g) the <em>IOLoop</em> is created very early on, more precisely it happens in the <strong><a href="https://github.com/mozilla/gecko-dev/blob/afdf8e01dd69dc75c88acebafd773508f97f91e4/xpcom/build/nsXPComInit.cpp#L451">NS_InitXPCOM2</a></strong> function. This is the code snippet that actually initiates the thread start:</p>
<pre>
...
scoped_ptr&lt;BrowserProcessSubThread&gt; ioThread(
    new BrowserProcessSubThread(BrowserProcessSubThread::IO));
...
ioThread-&gt;StartWithOptions(options)
...</pre>
<p><strong><em>ioThread</em></strong> is an instance of <strong><a href="https://github.com/mozilla/gecko-dev/blob/82ff7027aac0f7578d5c26567d8ac8e4b5d2b647/ipc/glue/BrowserProcessSubThread.h">BrowserProcessSubThread</a></strong> which inherits from <strong><a href="https://github.com/mozilla/gecko-dev/blob/e72ffaed408cab53a4cf4ca152089c9c38d2921c/ipc/chromium/src/base/thread.h">base::Thread</a></strong>, itself a subclass of <strong><a href="https://github.com/mozilla/gecko-dev/blob/e2ff646a3cd6d91020d037e633c9776026871b71/ipc/chromium/src/base/platform_thread.h">PlatformThread::Delegate</a></strong>.</p>
<p><strong>StartWithOptions</strong> is actually defined in <strong>base::Thread</strong>, the call will lead to a couple of more calls which will eventually end up at <strong>pthread_create</strong>. The function started in the new thread is <strong><a href="https://github.com/mozilla/gecko-dev/blob/e2ff646a3cd6d91020d037e633c9776026871b71/ipc/chromium/src/base/platform_thread_posix.cc#L36">ThreadFunc</a></strong>. <strong><em>ioThread</em></strong> object is passed along the calls and <strong><em>ioThread</em>-&gt;<a href="https://github.com/mozilla/gecko-dev/blob/e2ff646a3cd6d91020d037e633c9776026871b71/ipc/chromium/src/base/thread.cc#L139">ThreadMain()</a></strong> is called in the new thread.</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/8107/illu3_parent_startup.png" style="width: 900px; height: 469px;" /></p>
<p><strong>ThreadMain</strong> is now running in the <em>IOLoop</em> thread, it will call <strong>Init()</strong> of the current instance and also creates a <strong>MessageLoop</strong> instance and call the <strong>Run()</strong> method. We will <come any="" back="" is="" it="" later="" not="" of="" p="" part="" since="" startup="" that="" the="" thread="" to=""> </come>revisit this part later on, since it is not involved further in thread startup.</p>
<pre>
...
// The message loop for this thread.
MessageLoop message_loop(startup_data_-&gt;options.message_loop_type);
...
// Let the thread do extra initialization.
// Let's do this before signaling we are started.
Init();
...
message_loop.Run();
...
</pre>
<h4 id="Child"><strong>Child<a name="section_child"></a></strong></h4>
<p>For the child <em>IOLoop</em> thread spawn, we have to look at the <em>nuwa</em> process as a child of <em>b2g</em>, but also at the forked processes of <em>nuwa</em>.</p>
<p>Exactly how <em>b2g</em> spawns <em>nuwa</em> will be covered later; for now we assume that the <em>nuwa</em> process already exists. Once <em>nuwa</em> is created, we eventually reach the <strong><a href="https://github.com/mozilla/gecko-dev/blob/9ce7e9c08958e1c4f059fed6fedf07b49ab7285f/toolkit/xre/nsEmbedFunctions.cpp#L272">XRE_InitChildProcess</a></strong> function. This function is responsible for creating the <em>IOLoop</em> thread at <strong><a href="https://github.com/mozilla/gecko-dev/blob/9ce7e9c08958e1c4f059fed6fedf07b49ab7285f/toolkit/xre/nsEmbedFunctions.cpp#L493">this</a></strong> line:</p>
<pre>
process = new ContentProcess(parentHandle);
</pre>
<p>In the <strong><a href="https://github.com/mozilla/gecko-dev/blob/d768d99a05bb25d2b97bcdd3c08e887ae3a1c98d/dom/ipc/ContentProcess.h#L30">ContentProcess</a></strong> constructor, the <strong><a href="https://github.com/mozilla/gecko-dev/blob/fdbc9a2330b9e9c80aa81ff1bc39b39c04af2c9f/ipc/glue/ProcessChild.cpp#L19">ProcessChild</a></strong> constructor is called, which leads to a call of the <strong><a href="https://github.com/mozilla/gecko-dev/blob/a64afe22b9cae676a20c4d72776922ca6756648c/ipc/chromium/src/chrome/common/child_process.cc#L20">ChildProcess</a></strong> constructor. The important part to note here is, that the <strong>ChildProcess</strong> constructor gets passed a new instance of <strong><a href="https://github.com/mozilla/gecko-dev/blob/82ff7027aac0f7578d5c26567d8ac8e4b5d2b647/ipc/glue/IOThreadChild.h#L18">IOThreadChild</a></strong>. Within the constructor, the <strong><a href="https://github.com/mozilla/gecko-dev/blob/f5213d3e6666c532cbcd20837188d3b0fbcc950d/ipc/chromium/src/chrome/common/child_thread.cc#L33">Run()</a></strong> is called on the passed <strong>IOThreadChild</strong> object:</p>
<pre>
ChildProcess::ChildProcess(ChildThread* child_thread)
    : child_thread_(child_thread),
    ...
{
    ...
        child_thread_-&gt;Run();
}
</pre>
<p>From there, the <strong><a href="https://github.com/mozilla/gecko-dev/blob/e72ffaed408cab53a4cf4ca152089c9c38d2921c/ipc/chromium/src/base/thread.cc#L77">StartWithOptions</a></strong> function is called. At this point, it follows the same code path as for the main <em>IOLoop</em> startup the only exception is, that it is a <strong>IOThreadChild</strong> instance and not a <strong>BrowserProcessSubThread</strong> (see the b2g process illustration above for reference).</p>
<p>Below is an illustration of the <em>IOLoop</em> thread spawn in the&nbsp; <em>nuwa</em> process :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/8115/ipc_nuwa_ioloop.png" style="width: 650px; height: 566px;" /></p>
<p>This is the case for the original <em>nuwa</em> process. All future children will be forked from <em>nuwa</em>, and since <strong>fork</strong> only copies the thread it was called in to the new process, all threads so far would be lost.</p>
<p>We want to have all threads from <em>nuwa</em> (along with the <em>IOLoop</em>), in the forked process. In order to do that, <strong>pthread_create</strong> is not called directly, instead, the call is routed to <strong><a href="https://github.com/mozilla/gecko-dev/blob/58e49a079d477e5963a4180f674fbbd88534f76c/mozglue/build/Nuwa.cpp#L656">__wrap_pthread_create</a></strong> which wraps the real <strong>pthread_create</strong>. The purpose of the wrapper function, is to maintain a static list of startup information for all created threads (<strong><a href="https://github.com/mozilla/gecko-dev/blob/58e49a079d477e5963a4180f674fbbd88534f76c/mozglue/build/Nuwa.cpp#L255">sAllThreads</a></strong>). This list will be copied to the new process, the new process will then call <strong><a href="https://github.com/mozilla/gecko-dev/blob/58e49a079d477e5963a4180f674fbbd88534f76c/mozglue/build/Nuwa.cpp#L1390">RecreateThreads</a></strong> to restore all threads, based on the information maintained in the list.</p>
<h3 id="Channel">Channel<a name="section_channel"></a></h3>
<p>In order to be able to send and receive messages, we have to create a channel between the parent and the child. This section covers the classes used for this - the actual setup between parent and child will be covered once we get to the process spawning part.</p>
<p>Here a short illustration of the call flow:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/8109/ipc_channel_create.png" style="width: 790px; height: 353px;" /></p>
<ol>
 <li>&nbsp;The part of this flow is the creation of an <strong><a href="https://github.com/mozilla/gecko-dev/blob/eacb45e46d4b67a0d309e44af5de1ebede88d27b/ipc/chromium/src/chrome/common/ipc_channel.h#L15">IPC::Channel</a></strong> instance (the process of creating the instance will be covered later on). This class has two important attributes:
  <ul>
   <li><strong>channel_impl_</strong> which is the actual implementation of the channel (platform specific)</li>
   <li><strong>listener_</strong> this is used to pass incoming messages to</li>
  </ul>
 </li>
 <li>The posix class for the <strong>channel_impl_</strong> object can be found here (<strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/ipc_channel_posix.h#L24">Channel::ChannelImpl</a></strong>). <strong>Channel::ChannelImpl</strong> has the following important attributes:
  <ul>
   <li><strong>pipe_</strong> the file descriptor of the pipe (created by <strong>socketpair</strong>) for the parent side</li>
   <li><strong>client_pipe_</strong> the client end of the pipe</li>
   <li><strong>listener_</strong> the object that receives the incoming messages</li>
   <li><strong>output_queue_</strong> a queue where all outgoing messages are pushed to</li>
  </ul>
 </li>
 <li><strong>Channel::ChannelImpl</strong> has two overloaded constructor which can be used to create an object. One of them takes a file descriptor as the first argument which will be stored in <strong>pipe_</strong>. The more interesting constructor is the one which takes a <strong>channel_id</strong> (can also be empty). Both of them also take a <strong>Mode</strong> and a <strong>Listener*</strong> pointer as second and third argument. <strong>Mode</strong> just specifies if we are the server or the client. When the constructor with the <strong>channel_id</strong> is called, <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/ipc_channel_posix.cc#L303">CreatePipe</a></strong> will be called from there. We have to distinguish two different cases from here:
  <ul>
   <li><code>Mode == MODE_SERVER</code>: In this case, <strong>socketpair</strong> will be called. One end of the pipe will be stored in <strong>pipe_</strong> the other in <strong>client_pipe_</strong>. If <strong>channel_id</strong> is not empty, we insert a new entry in a <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/ipc_channel_posix.cc#L83">PipeMap</a></strong> where we associate <strong>client_pipe_</strong> with the given <strong>channel_id</strong>.</li>
   <li><code>Mode != MODE_SERVER</code>: In this case, we call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/ipc_channel_posix.cc#L129">ChannelNameToClientFD</a></strong>, which looks inside the <strong>PipeMap</strong> for an entry with the given <strong>channel_id</strong>. The result will be stored in <strong>pipe_</strong>.</li>
  </ul>
 </li>
 <li>After the object creation is completed, the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/ipc_channel_posix.cc#L395">Connect</a></strong> method can be called, this method will tell <em>libevent</em> to notify us whenever something has been written to <strong>pipe_</strong> and is ready to be received.</li>
 <li><strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/ipc_channel_posix.cc#L818">OnFileCanReadWithoutBlocking</a></strong> is the callback for this event. This function will then call a function to read the message from the file descriptor and then the message will be passed to the <strong>OnMessageReceived</strong> function inside the <strong>listener_</strong> (this will be covered later).</li>
</ol>
<h3 id="Spawning">Spawning</h3>
<p>In the previous section, we learned how <em>IOLoop</em> is created and how a channel is created. Throughout the last sections, we made the assumption that a process has already been started. This section will cover how those processes actually get started and how they connect to the IPC::Channel. We will again, have to distinguish between the <em>nuwa</em> process and the children of <em>nuwa</em>.</p>
<p>At this point I would suggest reading the <a href="https://developer.mozilla.org/en-US/docs/IPDL/Tutorial">IPDL Tutorial</a>, because from this point on we will reference to some of the classes generated from those IPDL files.</p>
<h3 id="Nuwa">Nuwa</h3>
<h4 id="creating_the_process"><strong>creating the process</strong></h4>
<p>Throughout the initialization phase of the <em>b2g</em> process, an instance of the singleton class <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.cpp#L36">PreallocatedProcessManagerImpl</a></strong> will be created. This instance is mainly accessed through a couple of static functions defined in the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.h#L39">PreallocatedProcessManager</a></strong> class. The purpose of this manager is to keep track of pre-allocated processes, this will be explained in more detail in the <a href="#section_preallocated">#Preallocated </a>section.</p>
<p>The implementation class has two important attributes:</p>
<ul>
 <li><strong>mSpareProcesses</strong> which is an array that contains the preallocated processes (will be important later on)</li>
 <li><strong>mPreallocatedAppProcess</strong> which will be the <em>nuwa</em> process</li>
</ul>
<p>This initialization happens inside the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentParent.cpp#L602">ContentParent::StartUp</a></strong> function, when executing the following code:</p>
<pre>
...
// Try to preallocate a process that we can transform into an app later.
PreallocatedProcessManager::AllocateAfterDelay();
...
</pre>
<p>This call will lead to the creation of the one and only instance of <strong>PreallocatedProcessManagerImpl</strong> is created (inside the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.cpp#L102">PreallocatedProcessManagerImpl::Singleton</a></strong> function). Right after the constructor call, the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.cpp#L125">Init</a></strong> function is invoked. Following the call flow from there, we will end up in <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.cpp#L174">Enable</a></strong>. <strong>Enable</strong> will then schedule the <em>nuwa</em> fork, with a 1 second delay (<a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.cpp#L23">DEFAULT_ALLOCATE_DELAY</a>), by calling <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.cpp#L237">ScheduleDelayedNuwaFork</a></strong>. This gives the <em>b2g</em> process enough time to finish its initialization.</p>
<p>As soon as the delay time has passed, the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.cpp#L255">DelayedNuwaFork</a></strong> function is called inside the main thread. Inside the function, we will call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentParent.cpp#L551">ContentParent::RunNuwaProcess</a></strong> which returns a pointer to a <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentParent.h#L66">ContentParent</a></strong> object, this object represents our <em>nuwa</em> process.</p>
<p>Inside the <strong>ContentParent</strong> constructor, a couple of interesting things happen.</p>
<ul>
 <li>we insert the new <strong>ContentParent</strong> into the global static list called <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentParent.cpp#L512">sContentParent</a></strong></li>
 <li>we create a <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/GeckoChildProcessHost.h#L28">GeckoChildProcessHost</a></strong> instance</li>
 <li>we call the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/GeckoChildProcessHost.cpp#L385">LaunchAndWaitForProcessHandle</a></strong> method of <strong>GeckoChildProcessHost</strong></li>
</ul>
<p>The <strong>LaunchAndWaitForProcessHandle</strong> method will schedule a task inside the <em>IOLoop</em> thread. In the <em>IOLoop</em> thread, <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/GeckoChildProcessHost.cpp#L479">RunPerformAsyncLaunch</a></strong> is called. After a few calls, we will end up in the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/base/process_util_linux.cc#L191">LaunchApp</a></strong> function. This is where the forking happens. After the <strong>fork</strong>, it will call <strong>execve</strong> in the child to re-execute itself.</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/8113/ipc_nuwa_fork.png" style="width: 1000px; height: 618px;" /></p>
<h4 id="connect_to_the_channel"><strong>connect to the channel</strong></h4>
<p>We covered the actual spawning, what's left is the part where the parent (<em>b2g</em>) and the child (<em>nuwa</em>) connect to the same IPC channel. We have two important calls for that on the parent side, one is made before the child was spawned, the other after the spawn. The first one is in the <strong>RunPerformAsynchLaunch</strong> function, before actually calling <strong>PerformAsynchLaunch</strong> (the position is marked with a 'x' in the above diagram), we call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/GeckoChildProcessHost.cpp#L405">InitializeChannel</a></strong> this will call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/child_process_host.cc#L77">CreateChannel</a></strong>. At this point a new <strong>IPC::Channel</strong> object is created, so please checkout the <a href="#channel_section">#Channel</a> section above.</p>
<p>The <strong>GeckoChildProcessHost</strong> object created inside the <strong>ContentParent</strong> constructor, serves as the <strong>listener_</strong> inside the <strong>IPC::Channel</strong> object. So <strong>GeckoChildProcessHost</strong> will supply the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/GeckoChildProcessHost.cpp#L895">OnMessageReceived</a></strong> function. There is nothing done there, it just saves all the incoming messages.</p>
<p>At this point we can consider the parent process to be connected to the channel. This was the first important call.</p>
<p>The second one is called as soon as <strong>LaunchAndWaitForProcessHandle</strong> returned (<em>nuwa</em> process is running at this point). Since the current <strong>OnMessageReceived</strong> handler doesn't do any good, we will have to assign a new <strong>listener_</strong>. In order to do that, this is being executed (<strong>mSubprocess</strong> is an instance of <strong>GeckoChildProcessHost</strong> which is created in <strong>ContentParent</strong>):</p>
<pre>
Open(mSubprocess-&gt;GetChannel(), mSubprocess-&gt;GetOwnedChildProcessHandle());
</pre>
<p>What happens now is a little complicated to explain just with text, so try to follow along, I will try to illustrate the process in the end, so you might want to follow the process again with the illustration.</p>
<p><strong>ContentParent</strong> actually extends <strong>PContentParent</strong> (this class is generated from the *.ipdl files, I can't reference to any github or mxr location), which is defined in <em>./objdir-gecko/ipc/ipdl/PContentParent.cpp</em> relative to the root directory of FirefoxOS. <strong>PContentParent</strong> has a member variable which will be important during the <strong>Open</strong> (defined in PContentParent.cpp) call.</p>
<ul>
 <li><strong>mChannel</strong> instance of <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/MessageChannel.h#L40">MessageChannel</a></strong></li>
</ul>
<p><strong>MessageChannel</strong> takes a <strong>MessageListener</strong> object as the one and only argument. <strong>mChannel</strong> is created during the <strong>PContentParent</strong> construction and passes <strong>this</strong> as the <strong>MessageListener</strong> object to <strong>MessageChannel</strong> (<strong>ContentParent</strong> extends <strong>MessageListener</strong> shown below.</p>
<p><strong>Open</strong> gets the <strong>IPC::Channel</strong> instance taken from <strong>mSubprocess</strong> (TODO: GetOwnedChildProcessHandle???) and calls <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/MessageChannel.cpp#L299">Open</a></strong> on <strong>mChannel</strong></p>
<pre>
auto PContentParent::Open(
        Channel::Transport* aTransport,
        ProcessHandle aOtherProcess,
        MessageLoop* aThread,
        mozilla::ipc::Side aSide) -&gt; bool
{
    mOtherProcess = aOtherProcess;
    return (mChannel).Open(aTransport, aThread, aSide);
}
</pre>
<p>As a side note, <strong>Channel::Transport</strong> is a typedef of <strong>IPC::Channel</strong>. <strong>aThread</strong> and <strong>aSide</strong> are set to 0 and <em>UnknownSide</em> by default if not specified. <strong>Open</strong> inside of the <strong>MessageChannel</strong> class will create a <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/MessageLink.h#L126">ProcessLink</a></strong>, <strong>this</strong> is passed to the constructor which will set <strong>mChan</strong> inside the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/MessageLink.h#L105">MessageLink</a></strong> class which <strong>ProcessLink</strong> inherits from.</p>
<p>After a instance of <strong>ProcessLink</strong> is created, we call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/MessageLink.cpp#L83">Open</a></strong> on it. This sets the member variable <strong>mTransport</strong> (which represents the IPC::Channel). So <strong>mTransport</strong> is the <strong>IPC::Channel</strong> pointer we retrieved from <strong>mSubprocess</strong></p>
<p>Since <strong>Connect</strong> has already been called when the <strong>IPC::Channel</strong> was created, we will schedule <strong>IOLoop</strong> to run <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/MessageLink.cpp#L309">OnTakeConnectedChannel</a></strong>. The channel state inside the <strong>MessageChannel</strong> object will be set to <strong>ChannelConnected</strong> and we also call <strong><a href="https://github.com/mozilla/gecko-dev/blob/eacb45e46d4b67a0d309e44af5de1ebede88d27b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc#L962">set_listener</a></strong> on the <strong>IPC::Channel</strong> instance to let it know, that <strong>ProcessLink</strong> will handle incoming messages, that means <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/glue/MessageLink.cpp#L270">OnMessageReceived</a></strong> inside <strong>ProcessLink</strong> is called. Those received messages will be passed to the <strong>MessageChannel</strong> and from there to the <strong>OnMessageReceived</strong> funciton inside the <strong>PContentParent</strong> class.</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/8117/ipc_parent_channel_connect.png" style="width: 1500px; height: 579px;" /></p>
<p>Now everything has been setup on the parent side. Let's get to the <em>nuwa</em> side.</p>
<p>After the <strong>fork</strong>, <em>nuwa</em> inherited all the open file descriptors from the parent <em>b2g</em>, one of them is its end of the pipe. Every child expects its end of the pipe to be file descriptor 3 (<strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/ipc_channel_posix.cc#L126">kClientChannelFd</a></strong>). In order to guarantee that file descriptor 3 will be the child's end of the pipe, we call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/base/file_descriptor_shuffle.h#L72">ShuffleFileDescriptors</a></strong>, this function will <strong>dup</strong> the child end of the pipe to 3. It also makes sure that in case 3 is a file descriptor needed by the child, that it will be remapped to the next available.</p>
<p>After the file descriptors have been remapped, we call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/base/process_util_posix.cc#L107">CloseSuperfluousFds</a></strong> to close all the ones that <em>nuwa</em> doesn't need. When everything is done, the child will call <strong>execve</strong> to re-execute itself.</p>
<p>From here please have a look at the <a href="#section_child">#Child</a> section, the actual channel connection will happen inside the <strong>ThreadMain</strong> function inside the <em>IOLoop</em> thread. <strong>ThreadMain</strong> will call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/child_thread.cc#L91">Init</a></strong> defined in <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/ipc/chromium/src/chrome/common/child_thread.h#L15">ChildThread</a></strong>. Inside this function, we will create a new <strong>IPC::Channel</strong> object, and you can refer to the <a href="#section_channel">#Channel</a> section from here. You will have to consider the part Mode != MODE_SERVER, therefore <strong>ChannelNameToClientFD</strong> will be called, which returns our magic file descriptor 3 (remember the child end of the pipe is mapped to this fd).</p>
<p>So now, we have a connection to the channel, what is left is to set the correct listener for the incoming messages. To do so, the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentProcess.cpp#L23">Init</a></strong> funciton inside <strong>ContentProcess</strong> is called. From there it will call <strong>Open</strong> in the <strong>PContentChild</strong> class, this will lead to the same call flow as for the parent in the above diagram. The only exception we have is that these calls originate from <strong>ContentChild</strong> which inherits from <strong>PContentChild</strong>.</p>
<h3 id="Preallocated">Preallocated<a name="section_preallocated"></a></h3>
<h4 id="creating_the_process_2"><strong>creating the process</strong></h4>
<p><img alt="" src="https://mdn.mozillademos.org/files/8111/ipc_fork_msg.png" style="width: 350px; height: 219px; float: right;" />A Preallocated process is a process fork()ed from <em>nuwa</em> which <em>b2g</em> keeps around, to turn it later into a app process. So at some point in time, <em>b2g</em> tells the preallocated process to turn into the game app that has been started on the phone. The process will then be assigned to the privileges of the app and the user will be able to do all the fancy stuff the app can do. As soon as a Preallocated process hasn been turned into an app, <em>b2g</em> will tell <em>nuwa</em> to create a new Preallocated process. So how does <em>b2g</em> tell <em>nuwa</em> to create a new Preallocated process? (at this point we have an active channel connection between <em>b2g</em> and <em>nuwa</em>)</p>
<p>For initiating the <strong>fork</strong>, <em>b2g</em> sends a message through the IPC channel and <em>nuwa</em> sends one back once it created the new process, the message contains the PID of the new process. On the right is a little illustration of the message flow.</p>
<p>Sending the initial message is initiated inside the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.cpp#L381">NuwaFork</a></strong> function. Remeber the <strong>mPreallocatedAppProcess</strong> is an instance of <strong>ContentParent</strong> and the invoked <strong>SendNuwaFork</strong> function is actually implemented inside <strong>PContentParent</strong>.</p>
<p>As soon as the child receives this messages, it will call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentChild.cpp#L1876">RecvNuwaFork</a></strong> which is defined in <strong>ContentChild</strong>. Following the calls from there, we will end up in <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/mozglue/build/Nuwa.cpp#L1602">ForkIPCProcess</a></strong>.</p>
<p>From there we call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/mozglue/build/Nuwa.cpp#L1564">PrepareProtoSockets</a></strong> which calls <strong>socketpair</strong> to create a new pipe for the new child and the parent.<br />
 It is also where <strong>fork</strong> is called and our new process is born. After the <strong>fork</strong> we will call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/mozglue/build/Nuwa.cpp#L1553">AddNewProcess</a></strong> inside <em>nuwa</em>. <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentChild.cpp#L1979">AddNewIPCProcess</a></strong> will then be responsible for initiating the second message. The message contains the parent side file descriptor for the pipe as well as the PID of the new process.</p>
<p>On the <em>b2g</em> side the <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentParent.cpp#L2314">RecvAddNewProcess</a></strong> will handle the message. It will create a new <strong>ContentParent</strong> instance. This time we call the second <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentParent.cpp#L1767">ContentParent</a></strong> constructor. It will create the <strong>ContentParent</strong> instance based on the already existing one and with the information of the new process. This also leads to a new instance in our static <strong>sContentParents</strong> list. This basically means that we have a <strong>ContentParent</strong> instance for each process that is running.</p>
<p>There is also a check in place which makes sure that only the <em>nuwa</em> process actually sends <strong>Msg_AddNewProcess</strong>:</p>
<pre>
...
if (!IsNuwaProcess()) {
...
</pre>
<p><strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/ContentParent.cpp#L1962">IsNuwaProcess</a></strong> checks a member variable of <strong>ContentParent</strong> wether or not it is <em>nuwa</em> who sent the message. This member variable can only be set from the parent side and it does this during the creation of the <strong>ContentParent</strong> for the <em>nuwa</em> process.</p>
<p>After initialization is finished, <strong>RecvAddNewProcess</strong> will then call <strong><a href="https://github.com/mozilla/gecko-dev/blob/6f80c55849c36f46f48941f735c8228b7e2f36d0/dom/ipc/PreallocatedProcessManager.cpp#L299">PublishSpareProcess</a></strong> to add the process to the managers list, which will keep track of all existing Preallocated processes. Whenever a Preallocated process will be turned into a app process, it will be removed from that spare processes list. Here an illustration of the process:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/8119/ipc_prealloc_fork.png" style="width: 1500px; height: 540px;" /></p>
<h4 id="connect_to_the_channel_2"><strong>connect to the channel</strong></h4>
<p>TODO: write it</p>
Revert to this revision