<<../_v1_banner.md>>
sysmgr is one of the two major pieces of Components v1 (appmgr being the other).
It is responsible for hosting the sys
realm that
contains global
system services. (The term realm
is used throughout this,
but note that in v1 it is a synonym for 'environment'.)
Most v1 components on Fuchsia today still run directly in the 'sys' realm, especially those responsible for system-wide and non-user-facing functionality. (Eventually, these will be migrated to the newer Components v2 runtime.) There also exist many (often user-facing) components in child realms under 'sys', such as components launched and managed by the Modular framework, that sysmgr is not involved in launching or managing.
The services available in the 'sys' realm and the components that sysmgr launches to provide those services are determined based on a set of sysmgr configuration files. This doc describes how to add to sysmgr's configuration, the different configration options sysmgr supports, and the configuration format.
At runtime, sysmgr loads all files present under /config/data in its namespace and parses them using the format described below. This directory is provided to sysmgr because it uses the 'config-data' feature in its component manifest, sysmgr.cmx. For more details, see the docs on the config-data feature.
You can make a new service available in the 'sys' realm by adding to sysmgr's configuration. There are two supported ways to do so:
-
Unless there is a specific reason to do otherwise, the centralized services.config file that is included in the core product config (core.gni) and all derivative products can be updated.
-
Alternatively, a new GN
config_data
target can be defined and included in product configurations to include an extra file in sysmgr's /config/data directory.A common reason to do this is to change the component that provides a given service depending on the product config, e.g. to use
fuchsia-pkg://fuchsia.com/foo#meta/foo.cmx
in product1.gni andfuchsia-pkg://fuchsia.com/bar#meta/bar.cmx
in product2.gni to provide servicefuchsia.some.Service
. A similar reason is to change the command line arguments passed to the component depending on the product config in order to modify its behavior.
TODO(fxbug.dev/48215): There are recognized deficiencies with the centralized services.config file, such as the fact that it is difficult to understand which services are actually available on a given build since it depends on whether the relevant package is available. We plan to address this during the migration to the newer v2 Component Runtime, but in the meantime using services.config is still the recommended default.
Note: With either option, you must take care to ensure that there are no conflicts in the
services
configuration. For this reason, the best practice is to only include sysmgrconfig_data
targets directly in product configuration files like core.gni, not in other GN group targets. For example, it is not recommended to depend on the sysmgrconfig_data
target in yourpackage
target as this makes it impossible to override the configuration in a later derived product .If there are conflicts present, they will be caught at build time and you will see an error similar to this:
Error: conflicts detected in sysmgr configuration Duplicate configuration for service fuchsia.my.Service in files: ../../some/path/default.config, ../../some/path/alternative.config
TODO(fxbug.dev/48223): As a TEMPORARY workaround for build errors like this, you can set the
dangerous_allow_sysmgr_config_conflicts
GN variable to true. This variable will be removed shortly and should only be used locally by developers, not in product configs, as it results in non-deterministic behavior (sysmgr may pick any of the conflicting configs to use).
In your BUILD.gn
:
config_data("my_service_config") {
for_pkg = "sysmgr"
sources = "my_service.config"
}
And then in the appropriate product.gni
:
base_package_labels += [
...
"//path/to:my_service_config",
...
]
sysmgr's configuration files are in JSON format. Each config file should have a single top-level JSON object, and the following keys are supported:
services
startup_services
apps
optional_services
update_dependencies
critical_components
The contents of all sysmgr config files are read from sysmgr's /config/data directory and merged at runtime to form sysmgr's overall configuration.
This is the most common configuration key and where most of sysmgr's
configuration comes from. Each entry in the services
map consists of a service
name and the component URL which provides it. Optionally, command line arguments
can be provided to the component by using an array instead of a string value.
{
"services": {
"fuchsia.foo.Service": "fuchsia-pkg://fuchsia.com/foo#meta/foo.cmx",
"fuchsia.bar.Service": [
"fuchsia-pkg://fuchsia.com/bar#meta/bar.cmx", "arg1", "arg2", "arg3"
]
}
}
The combined services
map across all config files defines the list of services
that are available in the sys
realm and that are available for other
components running in the sys
realm to request in their component manifests.
It is not possible to add services to the sys
realm in any other way; the list
of services is fixed at realm creation time.
Components in the services
map are started lazily as the services they provide
are connected to. In other words, in the example above foo.cmx
will not be
started until another component attempts to connect to fuchsia.foo.Service
. If
your component needs to be started eagerly, see startup_services
or apps
below.
Both of these keys perform similar functions; they cause sysmgr to eagerly
launch components right after it creates the sys
realm. The key difference is
that startup_services
should be used to eagerly launch a component which is
providing services to the sys
realm (i.e. there is an entry in the services
map that uses the component), whereas apps
should be used to eagerly launch a
component which does not provide any services to sys
.
For example, the following configuration would cause sysmgr to eagerly launch
the component that provides fuchsia.foo.Service
(the same as if another
component attempted to connect to the service) as well as an instance of
bar.cmx
and baz.cmx
with the given arguments:
{
"services": {
"fuchsia.foo.Service": "fuchsia-pkg://fuchsia.com/foo#meta/foo.cmx"
},
"startup_services": [
"fuchsia.foo.Service"
],
"apps": [
"fuchsia-pkg://fuchsia.com/bar#meta/bar.cmx",
[ "fuchsia-pkg://fuchsia.com/baz#meta/baz.cmx", "arg1", "arg2", "arg3" ]
]
}
It is important to not mix up usage of startup_services
and apps
. Using
apps
instead of startup_services
can result in sysmgr starting two separate
instances of your component, which is likely unintended. For example, the
example below would result in two instances of foo.cmx, one started eagerly and
the other started lazily when another component connects to
fuchsia.foo.Service
:
// WARNING: This is an example of what NOT to do.
{
"services": {
"fuchsia.foo.Service": "fuchsia-pkg://fuchsia.com/foo#meta/foo.cmx"
}
"apps": [
"fuchsia-pkg://fuchsia.com/foo#meta/foo.cmx"
]
}
optional_services
causes sysmgr to treat the corresponding services
entry as
optional. In concrete terms all this means is that sysmgr will skip printing
error logs if the launching the component that provides the service fails
because it was not present or if the component crashes or exits.
// WARNING: This is an example of what NOT to do.
{
"services": {
"fuchsia.foo.Service": "fuchsia-pkg://fuchsia.com/foo#meta/foo.cmx"
},
"optional_services: [
"fuchsia.foo.Service"
]
}
Warning: Here be dragons. You should not modify this configuration unless you are working on the Software Delivery stack.
update_dependencies
is a list of services that the package resolver depends
on. sysmgr implements the link between component resolution (through
fuchsia.sys.Loader) and the package resolver and needs this information to break
dependency cycles, e.g. so that starting the resolver does not first attempt to
resolve or update the resolver.
{
"services": {
"fuchsia.pkg.PackageResolver": "...",
"fuchsia.needed.for.Resolver": "..."
},
"update_dependencies: [
"fuchsia.pkg.PackageResolver",
"fuchsia.needed.for.Resolver"
]
}
The implementation details are subject to change, but as of 2020-04-29
update_dependencies
currently does two things:
-
All services listed in
update_dependencies
must be present somewhere in the combinedservices
map. If any service is missing, ephemeral package updates will be disabled. -
The
fuchsia.sys.Loader
implementation which sysmgr provides to ephemerally update packages in thesys
realm -PackageUpdatingLoader
- is configured to not use the package resolver (to avoid attempting to update) any package which provides a service listed inupdate_dependencies
.This avoids cycles, since the
fuchsia.pkg.PackageResolver
service thatPackageUpdatingLoader
uses to ephemerally resolve packages is itself part of thesys
realm.
If the auto_update_packages
GN arg is set to false, update_dependencies
has
no effect. It is only relevant for ephemeral package updates.
Disclaimer: this feature is not intended for general use. Please consult before using.
Critical components are a list of components which cause the system to reboot
if they ever terminate. The primary use-case are components which are critical to
the system's functionality and must always be running. Note that listing a
component under critical_components
does not mean it will necessarily launch
when sysmgr starts; the component may initially launch through other means,
such as via startup_services
.
Here is an example configuration snippet:
{
"startup_services": [
"fuchsia.update.Manager"
],
"services": {
"fuchsia.update.Manager": "fuchsia-pkg://fuchsia.com/system-update-checker#meta/system-update-checker.cmx"
},
"critical_components": [
"fuchsia-pkg://fuchsia.com/system-update-checker#meta/system-update-checker.cmx"
]
}
In the example above, system-update-checker.cmx
is launched when sysmgr starts
up because it provides a startup service. If system-update-checker.cmx ever
exits, the system is rebooted.