| // Copyright 2019 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. |
| library fuchsia.exception; |
| |
| using zx; |
| |
| /// The maximum amount of exceptions that will be returned by a call to |
| /// `ListProcessesWaitingOnException` or `WatchProcessesWaitingOnException`. |
| const MAX_EXCEPTIONS uint64 = 32; |
| |
| const MAX_FILTER_LENGTH uint64 = 32; |
| const MAX_FILTERS_PER_CALL uint64 = 32; |
| |
| /// Protocol meant for clients interested in obtaining processes that are |
| /// suspended waiting for an exception handler (in limbo). This is the core |
| /// feature that enables Just In Time (JIT) debugging. |
| /// |
| /// An example usage of this API would be having a debugger listen on limbo for |
| /// new processes. Then another component (eg. a CLI tool) could activate the |
| /// limbo, meaning that the system is now ready to capture crashing processes. |
| /// As the debugger got a notification that the limbo is now active, it can |
| /// correctly handle newly excepted processes and do its normal workflow. |
| @discoverable |
| protocol ProcessLimbo { |
| /// Set the active state of the limbo. Will trigger the `WatchActive` event |
| /// if there was a change, meaning that any listening components will receive |
| /// a notification. This includes the caller of `SetActive`. |
| /// |
| /// When a limbo is inactive, there will not be any processes waiting on it, |
| /// meaning that any waiting processes will be freed upon deactivating the |
| /// limbo. |
| SetActive(struct { |
| active bool; |
| }) -> (); |
| |
| /// Get whether the limbo is currently active. An active limbo could be empty |
| /// (not have any processes waiting on an exception). When a limbo is inactive, |
| /// there will not be any processes waiting on it. |
| GetActive() -> (struct { |
| is_active bool; |
| }); |
| |
| /// Watch for changes determining whether the limbo is currently active, |
| /// using a Hanging Get pattern. |
| WatchActive() -> (struct { |
| is_active bool; |
| }); |
| |
| /// List processes that are waiting on exceptions. |
| /// |
| /// Returns information on all the processes currently waiting on an exception. |
| /// The information provided will not contain any handle, so that it can be |
| /// transported over Overnet (see fxbug.dev/99649). |
| /// |
| /// The implementation should ensure that at any time there are no more than |
| /// MAX_EXCEPTIONS exceptions held in the limbo, so that no pagination is needed. |
| /// |
| /// Returns ZX_ERR_UNAVAILABLE if limbo is not active. |
| ListProcessesWaitingOnException() -> (struct { |
| exception_list vector<ProcessExceptionInfo>:MAX_EXCEPTIONS; |
| }) error zx.status; |
| |
| /// Watch for processes that are waiting on exceptions, using a Hanging Get |
| /// Pattern. |
| /// |
| /// Returns information on all the processes currently waiting on an exception. |
| /// The information provided is intended to correctly identify an exception |
| /// and determine whether the caller wants to actually handle it. |
| /// To retrieve an exception, use the `GetException` call. |
| /// |
| /// Returns ZX_ERR_UNAVAILABLE if limbo is not active. |
| /// Returns ZX_ERR_CANCELED if there was an outstanding call and the limbo |
| /// becomes inactive. |
| /// |
| /// NOTE: The `process` and `thread` handle will only have the ZX_RIGHT_READ |
| /// right, so no modification will be able to be done on them. |
| WatchProcessesWaitingOnException() -> (resource struct { |
| exception_list vector<ProcessExceptionMetadata>:MAX_EXCEPTIONS; |
| }) error zx.status; |
| |
| /// Removes the process from limbo and retrieves the exception handle and |
| /// associated metadata from an exception. |
| /// |
| /// Use `ListProcessesWaitingOnException` to choose a `process_koid` from the |
| /// list of available exceptions. |
| /// |
| /// Returns ZX_ERR_NOT_FOUND if the process is not waiting on an exception. |
| /// Returns ZX_ERR_UNAVAILABLE if limbo is not active. |
| RetrieveException(struct { |
| process_koid zx.koid; |
| }) -> (resource struct { |
| process_exception ProcessException; |
| }) error zx.status; |
| |
| /// Removes the process from limbo, releasing the exception. This will make |
| /// it "bubble up" beyond the scope of of this limbo, making it |
| /// unretrievable in the future from here. |
| ReleaseProcess(struct { |
| process_koid zx.koid; |
| }) -> (struct {}) error zx.status; |
| |
| /// Adds filters to the limbo. Filters determine what processes the limbo |
| /// will store when receiving an exception. Repeated filters will be |
| /// ignored. Filters work by "filtering out" processes. It means that if a |
| /// filter matches, that process won't get included. |
| /// |
| /// Filters work by substring matching. This means that a process name has |
| /// to have the filter as a substring in order to match it. Example: |
| /// |
| /// Filter = "dev". |
| /// Process = "process" won't match. |
| /// Process = "devcoordinator" will match. |
| /// |
| /// Adding filters is transactional: either all of them go in, or none at |
| /// all. The maximum amount of filters is determined by |
| /// `MAX_FILTERS_PER_CALL`. If the maximum is exceeded, ZX_ERR_NO_RESOURCES |
| /// is returned. |
| /// |
| /// Changing filters have no effect on processes that are currently waiting |
| /// on an exception, but rather which future processes that will remain in |
| /// the limbo. |
| /// |
| /// Returns ZX_ERR_UNAVAILABLE if limbo is not active. |
| AppendFilters(struct { |
| filters vector<string:MAX_FILTER_LENGTH>:MAX_FILTERS_PER_CALL; |
| }) -> (struct {}) error zx.status; |
| |
| /// Removes filters to the limbo. Any filters that are not currently present |
| /// on the limbo will be ignored. |
| /// |
| /// Returns ZX_ERR_UNAVAILABLE if limbo is not active. |
| RemoveFilters(struct { |
| filters vector<string:MAX_FILTER_LENGTH>:MAX_FILTERS_PER_CALL; |
| }) -> (struct {}) error zx.status; |
| |
| /// Returns filters that are currently active within the limbo. If the limbo |
| /// is inactive, it will return an empty vector. |
| GetFilters() -> (struct { |
| filters vector<string:MAX_FILTER_LENGTH>:MAX_FILTERS_PER_CALL; |
| }); |
| }; |
| |
| /// Intended to be an information-only message that contains no handle. |
| type ProcessExceptionInfo = table { |
| 1: info ExceptionInfo; |
| 2: process_name string:zx.MAX_NAME_LEN; |
| 3: thread_name string:zx.MAX_NAME_LEN; |
| }; |
| |
| /// Intended to be read only metadada associated with an exception waiting in |
| /// limbo. The handles provided will only have read-only access to the resource, |
| /// so no modification can be done to them. |
| /// |
| /// NOTE: Both `process` and `thread` will be valid if present. |
| type ProcessExceptionMetadata = resource table { |
| 1: info ExceptionInfo; |
| |
| /// Only has ZX_RIGHT_READ and ZX_RIGHT_GET_PROPERTY rights. |
| 2: process zx.handle:PROCESS; |
| |
| /// The thread that generated the exception. |
| /// The process may have other threads that are not reflected here. |
| /// Only has ZX_RIGHT_READ and ZX_RIGHT_GET_PROPERTY rights. |
| 3: thread zx.handle:THREAD; |
| }; |