Component lifecycle

This document describes how Component manager interacts with individual component instances to manage their lifecycle.

Lifecycle states

Component instances progress through the following major lifecycle states:

Component lifecycle states

Component instances may retain isolated persistent state on a storage medium while they are not running, which can be used to help them maintain continuity across restarts.

Created

A component instance may be created in the following ways:

  • Configured as the root component of Component manager.
  • Statically discovered as the child of another component.
  • Dynamically created at runtime in a collection.

Every component instance has a component URL that describes how to resolve the component, and a moniker that uniquely identifies the instance by its path from the root. For more details, see component identifiers.

Once created, a component instance can then be resolved or destroyed.

Resolved

Resolving a component instance fetches the component declaration for the specified component URL. Component manager resolves component URLs by finding a component resolver that supports a matching URL scheme in the environment. Developers can resolve components manually using the ffx component resolve command.

Components must successfully resolve before they can be started.

Started

Starting a component instance loads and runs the component's program and provides it access to the capabilities that it requires.

The most common reason for starting a component instance is when another component binds to one of its exposed capabilities. Developers can also start components manually using the ffx component start command.

Once started, a component instance continues to run until it is stopped.

Stopped

Stopping a component instance terminates the component's program but preserves its persistent state. Components enter this state when their program exits, as defined by the component's runner.

The Component Framework may stop a component instance for the following reasons:

  • The component is about to be destroyed.
  • The system is shutting down.

A component can implement a lifecycle handler (example) to receive a notification of events such as impending termination. Note that components may not receive these events in circumstances such as resource exhaustion, crashes, or power failure.

Once stopped, a component instance may be restarted or shutdown.

Shutdown

Component manager sets the final execution state of a component instance to shutdown to indicate that it cannot be restarted and to signal that the instance can be safely destroyed.

Destroyed

A component instance may be destroyed in the following ways:

  • Dynamically removed from a collection at runtime. This is also true if the component is a descendant of another component being removed.

Once destroyed, Component manager completely removes the instance from the component topology, including all persistent state. New instances of the same component will each have their own identity and state distinct from all prior instances.

Lifecycle actions

This section describes common actions used by the Component Framework to transition the lifecycle state of component instances.

Bind

A component instance A binds to another component instance B when A connects to some capability that is provided by B. This causes component B to start if it is not already running.

Concretely, there are two ways that A can bind to B:

  • A connects to a capability in its namespace which is exposed or offered by B. This is the most common way.
  • A binds to the fuchsia.component.Binder framework protocol which is exposed or offered by B. Unlike a traditional capability, this protocol is implemented by the component framework.

Shutdown ordering

When the component framework decides to shut down a component, it will shut down the component and its children in an order determined by their dependencies. This behavior is recursive which means that shutting down a component will shut down the full topology under that component.

Components within a realm are shut down in a specific order, which is based on the strong dependencies between those components. The dependencies between components form a Directed Acyclical Graph (DAG), and components are shut down in target-to-source order.

All capabilities are considered in the dependency graph. Capabilities are offered as a strong dependency by default, but a client can offer a dependency by specifying dependency: weak.

As an example, imagine a realm with components A, B, C, D. There are the following offers:

  • A strongly offers a capability to B and C.
  • B strongly offers a capability to C.
  • C weakly offers a capability to B.

Here is a drawing of the realm in question:

Component shutdown example

The shutdown ordering would be the following:

  • D and C can be shut down in any order as they have no dependents.
  • B can then be shut down after C.
  • A can then be shut down after B.

Weak dependencies

Remember that the component dependencies forms a DAG, meaning there are no cycles. This means that in the example above, C cannot strongly offer a capability to A.

However, C is allowed to offer a capability to A with dependency: "weak". A weak dependency is not considered to be a part of the dependency DAG and it will not affect shutdown ordering.