blob: 947a7b5512e32476bb28b5180354886b47428f26 [file] [log] [blame] [view]
# component manager
Reviewed on: 2019-07-12
Component manager is the program which runs and manages v2 components. More
about what components are, what semantics they provide, and how to use them is
available [here](/docs/the-book/components/README.md).
## Building
Component manager should be included in all builds of Fuchsia, but if missing
can be added to builds by including `--with //src/sys/component_manager` to the
`fx set` invocation.
### Faster builds
Rust optimizations (and, in particular, link time optimizations) require a
significant amount of time, causing slow builds. For faster local development,
adding the following arguments to your `fx set` line will significantly
reduce build times by disabling optimizations:
```sh
fx set ... --args rust_override_opt='"0"' --args rust_override_lto='"none"'
```
## Running
Component manager runs by default on all Fuchsia builds.
## Testing
Unit tests for component manager are available in the `component_manager_tests`
package.
```
$ fx test component_manager_tests
```
Integration tests are also available in the following packages:
- `hub_integration_test`
- `storage_integration_test`
- `routing_integration_test`
- `elf_runner_test`
- `no_pkg_resolver_test`
## Source layout
The entrypoint is located in `src/main.rs`, and the core model implementation is
under `src/model/`. Unit tests are co-located with the code, with the exception
of `src/model/` which has unit tests in `src/model/tests/`. Integration tests
live in `tests/`.
## Development best practices
### `Arc<Realm>` and `fasync::spawn`
#### Problem
Many parts of the code need access to a `Realm`. Some of those are long-running asynchronous
operations, such as hosting a pseudo-fs directory with a closure (see `//src/sys/lib/directory_broker`).
These operations are executed on the global executor through `fasync::spawn`.
These closures should never capture an `Arc<Realm>`, as the closures lifetime is not bound to the `Realm`,
even though it is conceptually tied to the life of `Realm`. This can lead to memory leaks / reference cycles.
#### Solution
Use `WeakRealm`, which wraps a `Weak<Realm>` (weak pointer to `Realm`) along with the `AbsoluteMoniker` of
the realm, for good error-reporting when the `Realm` has been destroyed.
```
use crate::model::realm::{Realm, WeakRealm};
let realm: Arc<Realm> = model.look_up_realm(...)?;
let captured_realm: WeakRealm = realm.as_weak();
fasync::spawn(async move {
let realm = match captured_realm.upgrade() {
Ok(realm) => realm,
Err(e) => {
log::error!("failed to upgrade WeakRealm: {}", e);
return;
}
};
...
});
```