| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| @available(added=7) |
| library fuchsia.component.runner; |
| |
| using fuchsia.component; |
| using fuchsia.data; |
| using fuchsia.diagnostics.types; |
| using fuchsia.io; |
| using fuchsia.mem; |
| using fuchsia.process; |
| using fuchsia.url; |
| using zx; |
| |
| const MAX_NAMESPACE_COUNT uint32 = 32; |
| const MAX_HANDLE_COUNT uint32 = 128; |
| |
| /// A protocol used for running components. |
| /// |
| /// This protocol is implemented by components which provide a runtime |
| /// environment for other components. |
| /// |
| /// Note: The component manager is the only intended direct client of this |
| /// interface. |
| @discoverable |
| protocol ComponentRunner { |
| /// Start running a component instance described by `start_info`. |
| /// |
| /// Component manager binds and uses `controller` to control the |
| /// lifetime of the newly started component instance. |
| /// |
| /// Errors are delivered as epitaphs over the `ComponentController` |
| /// protocol. In the event of an error, the runner must ensure that |
| /// resources are cleaned up. |
| /// |
| /// Errors: |
| /// |
| Start(resource struct { |
| start_info ComponentStartInfo; |
| controller server_end:ComponentController; |
| }); |
| }; |
| |
| /// A single component namespace entry, which describes a namespace mount point |
| /// (`path`) and the directory backing it (`directory`). This type is usually |
| /// composed inside a vector. See `ComponentStartInfo.ns` for more details. |
| type ComponentNamespaceEntry = resource table { |
| /// The mount point for the directory, including a |
| /// leading slash. For example: "/pkg", "/svc", or "/config/data". |
| 1: path string:fuchsia.component.MAX_PATH_LENGTH; |
| |
| /// The directory mounted at the above `path`. |
| 2: directory client_end:fuchsia.io.Directory; |
| }; |
| |
| /// Parameters for starting a new component instance. |
| type ComponentStartInfo = resource table { |
| /// The resolved URL of the component. |
| /// |
| /// This is the canonical URL obtained by the component resolver after |
| /// following redirects and resolving relative paths. |
| 1: resolved_url fuchsia.url.Url; |
| |
| /// The component's program declaration. |
| /// This information originates from `ComponentDecl.program`. |
| 2: program fuchsia.data.Dictionary; |
| |
| /// The namespace to provide to the component instance. |
| /// |
| /// A namespace specifies the set of directories that a component instance |
| /// receives at start-up. Through the namespace directories, a component |
| /// may access capabilities available to it. The contents of the namespace |
| /// are mainly determined by the component's `use` declarations but may |
| /// also contain additional capabilities automatically provided by the |
| /// framework. |
| /// |
| /// By convention, a component's namespace typically contains some or all |
| /// of the following directories: |
| /// |
| /// - "/svc": A directory containing services that the component requested |
| /// to use via its "import" declarations. |
| /// - "/pkg": A directory containing the component's package, including its |
| /// binaries, libraries, and other assets. |
| /// |
| /// The mount points specified in each entry must be unique and |
| /// non-overlapping. For example, [{"/foo", ..}, {"/foo/bar", ..}] is |
| /// invalid. |
| 3: ns vector<ComponentNamespaceEntry>:MAX_NAMESPACE_COUNT; |
| |
| /// The directory this component serves. |
| 4: outgoing_dir server_end:fuchsia.io.Directory; |
| |
| /// The directory served by the runner to present runtime information about |
| /// the component. |
| 5: runtime_dir server_end:fuchsia.io.Directory; |
| |
| /// The numbered handles that were passed to the component. |
| /// |
| /// If the component does not support numbered handles, the runner is expected |
| /// to close the handles. |
| 6: numbered_handles vector<fuchsia.process.HandleInfo>:MAX_HANDLE_COUNT; |
| |
| /// Binary representation of the component's configuration. |
| /// |
| /// # Layout |
| /// |
| /// The first 2 bytes of the data should be interpreted as an unsigned 16-bit |
| /// little-endian integer which denotes the number of bytes following it that |
| /// contain the configuration checksum. After the checksum, all the remaining |
| /// bytes are a persistent FIDL message of a top-level struct. The struct's |
| /// fields match the configuration fields of the component's compiled manifest |
| /// in the same order. |
| 7: encoded_config fuchsia.mem.Data; |
| |
| /// An eventpair that debuggers can use to defer the launch of the component. |
| /// |
| /// For example, ELF runners hold off from creating processes in the component |
| /// until ZX_EVENTPAIR_PEER_CLOSED is signaled on this eventpair. They also |
| /// ensure that runtime_dir is served before waiting on this eventpair. |
| /// ELF debuggers can query the runtime_dir to decide whether to attach before |
| /// they drop the other side of the eventpair, which is sent in the payload of |
| /// the DebugStarted event in fuchsia.sys2.events. |
| 8: break_on_start zx.handle:EVENTPAIR; |
| }; |
| |
| /// A protocol for binding and controlling the lifetime of a component instance |
| /// started using `ComponentRunner.Start()`. The component manager is the |
| /// intended direct client of this protocol. |
| /// |
| /// When the controlled component instance terminates or becomes inaccessible |
| /// for any reason, the server closes the connection with an epitaph. |
| /// |
| /// LIFECYCLE |
| /// |
| /// A component may exist in one of two states: `Started`, or `Stopped`. The |
| /// component is `Started` from the time `ComponentRunner.Start()` is called |
| /// until the ComponentRunner closes the ComponentController handle. The |
| /// component then transitions to `Stopped`. |
| /// |
| /// Component manager uses ComponentController to terminate a component in two |
| /// steps: |
| /// 1) Component manager calls `Stop()` to indicate that the ComponentRunner |
| /// should stop a component's execution and close this connection with an |
| /// epitaph. |
| /// 2) If after some time the ComponentController is not closed, component |
| /// manager calls `Kill()` to indicate that the ComponentRunner must halt a |
| /// component's execution immediately, and then close this connection with |
| /// an epitaph. The component manager may wait some period of time after |
| /// calling `Kill()` before closing the ComponentController channel, but |
| /// makes no guarantees it will wait or for how long. |
| /// |
| /// Component manager first waits for the ComponentController to close, and |
| /// then tears down the namespace it hosts for the stopped component. Component |
| /// manager may call `Kill()` without first having called `Stop()`. |
| /// |
| /// EPITAPH |
| /// |
| /// This protocol sends a FIDL epitaph to indicate that the component instance |
| /// has been terminated. The component runner is expected to clean up all |
| /// resources attributed to the component before closing the connection. |
| /// |
| /// The following epitaphs may be sent by the server on error: |
| /// - `ZX_OK`: The component exited successfully, typically because the |
| /// component was asked to stop or it decided independently to exit. |
| /// - `INVALID_ARGUMENTS`: |
| /// * `start_info.resolved_url` is not supported by this |
| /// runner; |
| /// * `start_info` contains missing or invalid arguments. |
| /// - `INSTANCE_CANNOT_START`: The runner could not start the component. |
| /// For example, a critical part of the program could not be found or |
| /// loaded, or the referenced binary was invalid for this runner. |
| /// - `RESOURCE_UNAVAILABLE`: The component could not be launched due to |
| /// lack of resources. |
| /// - `INTERNAL`: An unexpected internal runner error was encountered. |
| /// - `INSTANCE_DIED`: The component instance was started but |
| /// subsequently terminated with an error. |
| /// - Other status codes (e.g. `ZX_ERR_PEER_CLOSED`) may indicate a failure |
| /// of the component runner itself. The component manager may respond to such |
| /// failures by terminating the component runner's job to ensure system |
| /// stability. |
| protocol ComponentController { |
| /// Request to stop the component instance. |
| /// |
| /// After stopping the component instance, the server should close this |
| /// connection with an epitaph. After the connection |
| /// closes, component manager considers this component instance to be |
| /// Stopped and the component's namespace will be torn down. |
| Stop(); |
| |
| /// Stop this component instance immediately. |
| /// |
| /// The ComponentRunner must immediately kill the component instance, and |
| /// then close this connection with an epitaph. After the connection |
| /// closes, component manager considers this component instance to be |
| /// Stopped and the component's namespace will be torn down. |
| /// |
| /// In some cases Kill() may be issued before Stop(), but that is not |
| /// guaranteed. |
| Kill(); |
| |
| /// Event for runners to publish diagnostics to the platform. |
| /// |
| /// This event signals to the platform that the runner for this |
| /// component is publishing diagnostics about the runtime of the |
| /// component. The component manager may optionally expose this data |
| /// to clients. |
| -> OnPublishDiagnostics(resource struct { |
| payload fuchsia.diagnostics.types.ComponentDiagnostics; |
| }); |
| }; |