ELF Runner (Components v2)

<<../_v2_banner.md>>

The ELF runner is the runner responsible for launching components based on standard executable files (ELF format).

A capability to the ELF runner service is offered to the root component under the name elf. For other components to use the ELF runner, the capability must be explicitly routed to them.

For a detailed explanation of how processes are created, please see //docs/concepts/booting/program_loading.md.

Using the ELF Runner

To use the ELF runner, the component must add a program block, containing:

  • the binary
  • the runner the program uses (unless that is already included via a CML shard)
  • (optionally) program arguments that should be used.

The ELF runner receives instructions from the program section of the component manifest. The binary field holds the path to an executable file in the package the manifest comes from, and the args field holds any additional string arguments that should be provided to the process when it is created.

The main_process_critical field may be used to mark the component's first process as critical to component manager's job, which will cause component manager (and all components) to be terminated if the process exits with a non-zero code. An allowlist is used to control which components may use this field.

This is an example manifest that launches bin/echo with the arguments Hello and world!. It assumes that the ELF runner capability has been offered to the component under the name elf:

{
    program: {
        runner: "elf",
        binary: "bin/echo",
        args: [ "Hello", "world!" ],
    }
}

Lifecycle

Components have a lifecycle. Components run by the ELF runner can integrate with the lifecycle if you add a lifecycle attribute to your component manifest. Currently stop is the only method in the Lifecycle protocol.

{
    program: {
        runner: "elf",
        binary: "bin/echo",
        lifecycle: { stop_event: "notify" },
    }
}

The program should take the handle to the Lifecycle channel and serve the Lifecycle protocol on that channel. The component should exit after receiving and processing the stop call. For an example see this sample code.

The ELF Runner monitors the process it started for the program binary of the component. If this process exits, the ELF runner will terminate the component‘s execution context, which includes the component’s job and all subprocesses.

Forwarding stdout and stderr streams

The stdout and stderr streams of ELF components can be routed to the LogSink service. By default, the ELF runner doesn't route these streams to any output sink. Therefore, any write to these streams, such as printf, is lost and can be considered a no-op. If your component prints diagnostics messages to either of these streams, you should forward the streams to the LogSink service.

To enable this feature, add the following to your manifest file:

{
    include: [ "sdk/lib/diagnostics/syslog/elf_stdio.shard.cml" ],
    ...
}

After including this shard, all writes to stdout are logged as INFO messages, and all writes to stderr are logged as WARN messages. Messages are split by newlines and decoded as UTF-8 strings. Invalid byte sequences are converted to the U+FFFD replacement character, which usually looks like .

Note: There are known issues where messages from ZX_ASSERT_... in C/C++ components and Error objects returned in main in Rust components are lost. For more information, see fxb-72178 and fxb-72764 respectively.