Skip to content

Latest commit

 

History

History
 
 

child-writer

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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 and stderr in a stream fashion. This also means that we can't use the nice process.send IPC communication channel directly that child_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 or kdesudo.

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!