
The `child-writer` module is not re-used by both the GUI and the CLI, so it makes sense to have it in `lib/child-writer`. Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
3.0 KiB
Etcher Child Writer
This module is in charge of dealing with the gory details of elevating and managing the child writer process. As a word of warning, it contains tons of workarounds and "hacks" to deal with platform differences, packaging, and inter-process communication. This empowers us to write this small guide to explain how it works in a more high level manner, hoping to make it easier to grok for contributors.
The problem
Elevating a forked process is an easy task. Thanks to the widely available NPM
modules to display nice GUI prompt dialogs, elevation is just a matter of
executing the process with one of those modules instead of with child_process
directly.
The main problems we faced are:
-
The modules that implement elevation provide "execution" support, but don't allow us to fork/spawn the process and consume its
stdout
andstderr
in a stream fashion. This also means that we can't use the niceprocess.send
IPC communication channel directly thatchild_process.fork
gives us to send messages back to the parent. -
Since we can't assume anything from the environment Etcher is running on, we must make use of the same application entry point to execute both the GUI and the CLI code, which starts to get messy once we throw
asar
packaging into the mix. -
Each elevation mechanism has its quirks, mainly on GNU/Linux. Making sure that the forked process was elevated correctly and could work without issues required various workarounds targeting
pkexec
orkdesudo
.
How it works
The Etcher binary runs in CLI or GUI mode depending on an environment variable
called ELECTRON_RUN_AS_NODE
. When this variable is set, it instructs Electron
to run as a normal NodeJS process (without Chromium, etc), but still keep any
patches applied by Electron, like asar
support.
When the Etcher GUI is ran, and the user presses the "Flash!" button, the GUI creates an IPC server, and forks a process called the "writer proxy", passing it all the required information to perform the flashing, such as the image path, the device path, the current settings, etc.
The writer proxy then checks if its currently elevated, and if not, prompts the user for elevation and re-spawns itself.
Once the writer proxy has enough permissions to directly access devices, it
spawns the Etcher CLI passing the --robot
option along with all the
information gathered before. The --robot
option basically tells the Etcher
CLI to output state information in a way that can be very easily parsed by the
parent process.
The output of the Etcher CLI is then sent to the IPC server that was opened by the GUI, which nicely displays them in the progress bar the user sees.
Summary
There are lots of details we're omitting for the sake of clarity. Feel free to dive in inside the child writer code, which is heavily commented to explain the reasons behind each decision or workaround.
Don't hesitate in getting in touch if you have any suggestion, or just want to know more!