-
Notifications
You must be signed in to change notification settings - Fork 111
Document implementation-defined resource limits in Canonical ABI #616
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -106,6 +106,31 @@ nature of eliminating `realloc`, switching to [lazy lowering] would obviate | |
| this issue, allowing guest wasm code to handle failure by eagerly returning | ||
| some value of the declared return type to indicate failure. | ||
|
|
||
| ### Implementation-Defined Limits | ||
|
|
||
| Beyond the explicit `trap_if` checks in the Python code below, implementations | ||
| may also trap during any cross-component call when | ||
| implementation-defined resource limits have been reached. In particular: | ||
| * An implementation may trap when the handles table has reached an | ||
| implementation-defined capacity that is at or below `Table.MAX_LENGTH`. This | ||
| allows implementations to bound the host-side memory used to track resources, | ||
| waitables and other table elements. This is analogous to how `memory.grow` | ||
| may non-deterministically return `-1` in Core WebAssembly when the | ||
| implementation cannot satisfy the allocation. | ||
|
Comment on lines
+114
to
+119
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
One difference is that Reaching a max table capacity is similar to OOM and many languages don't handle that. Even Rust doesn't support that on stable yet. Because of that, I think trapping is indeed a reasonable default for the C/M. OTOH, there are also environments where the guest is fully prepared to handle resource exhaustion and would much rather prefer missing out on a single resource over trapping the entire process.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great points. For host-implemented functions being passed handles from guest-to-host, I think the same reasoning as above applies (the host should ideally fail gracefully or, because it's always allowed, trap; too-many-host-handles seems like it'd be pretty rare in non-pathological scenarios so trapping seems Fine). When the guest is lowering a handle with the current eager ABI, indeed there is already a But overall, I think this bullet might not be needed either. |
||
| * An implementation may trap when the total size of values being transferred | ||
| across a component boundary (via lifting or lowering) exceeds an | ||
| implementation-defined limit. For example, lifting a `list<u8>` of length N | ||
| from guest linear memory requires an intermediate allocation of at least N | ||
| bytes on the host, and implementations may refuse to perform such an | ||
| allocation when N is very large. | ||
|
Comment on lines
+120
to
+125
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand why we need to allow traps with the current ABI. If/when we have lazy lowering, can this trap condition be removed? There is no way for a guest to find out what the host considers "very large". Microcontrollers might already find 1MB very large. We shouldn't end up in a situation where guests need to play a game of "guess the host's limit" and be penalized with a trap in case they guess wrong.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. Even with our current eager ABI, because hosts have host powers, it seems like, as long as the WIT function signature allows some sort of graceful failure return value, a host should ideally return a failure value on too-large-parameter instead of trapping. (Adding lazy lowering will just add the equivalent expressive power to wasm-implemented functions.) Now I can imagine that implementing graceful failure would take time and effort and so trapping might be the right choice in the short term. However, because a host runtime is always allowed to unilaterally abort execution (think: host crash, timeout), and because trap = "abort execution" in component-land, trapping is just the host exercising its freedom and it's more of a quality of implementation issue. I think what both these arguments mean is that we don't need this bullet. |
||
|
|
||
| In both cases, the resulting trap is non-deterministic: the same call with the | ||
| same arguments may succeed at one point and trap at another depending on the | ||
| current resource usage of the implementation. Guest code should be written | ||
| defensively, but WASI-level interfaces are also encouraged to use `result` | ||
| return types with explicit error cases for resource exhaustion where possible, | ||
| enabling guests to handle limits gracefully rather than trapping. | ||
|
|
||
| ## Embedding | ||
|
|
||
| A WebAssembly Component Model implementation will typically be *embedded* into | ||
|
|
@@ -492,7 +517,9 @@ free list in the free elements of `array`. | |
|
|
||
| The limit of `2**28` ensures that the high 2 bits of table indices are unset | ||
| and available for other use in guest code (e.g., for tagging, packed words or | ||
| sentinel values). | ||
| sentinel values). As described in the [Introduction](#introduction), | ||
| implementations may trap at a lower limit than `MAX_LENGTH` based on | ||
| implementation-defined resource constraints. | ||
|
|
||
|
|
||
| #### Resource State | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure if we should place this here or in the Explainer.md