pchickey opened PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
sunfishcode submitted PR Review.
sunfishcode submitted PR Review.
sunfishcode created PR Review Comment:
system-interface 0.1.0 now has
FileIoExt::allocate
which does this.
sunfishcode created PR Review Comment:
Ah, sorry I neglected to mention it, that's in a separate crate -- fs-set-times. If you use that crate's SystemTimeSpec in place the
FilestatSetTime
definition above, then usage is basicallyuse fs_set_times::SetTimes; file.set_times(atime, mtime)
Or something like
pub trait WasiFile: FileIoExt + SetTimes
might work too.
sunfishcode created PR Review Comment:
cap_std::fs::Metadata
implements Unix'sMetadataExt
on Unix, and Windows'MetadataExt
on Windows, with functions that provide all the info here, though I can look into something more portable too.
sunfishcode created PR Review Comment:
Yeah, cap-std is following std in this respect. On Unix,
PermissionsExt
does have afrom_mode
, but I'll think about adding something portable too.
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey submitted PR Review.
pchickey created PR Review Comment:
I'll prototype something portable that lets us implement this in the wasi-c2 crate, and we can figure out where to upstream it after.
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey submitted PR Review.
pchickey created PR Review Comment:
I came up with something janky here which depends on nightly to work on windows...
pchickey submitted PR Review.
pchickey created PR Review Comment:
Implemented this except for making the flags canonical, which is the sort of thing we can sort out later.
On windows, should we reject this with an error or should we silently do nothing?
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
ueno submitted PR Review.
ueno created PR Review Comment:
Probably a dumb question, but I wonder if there is a reason to have separate structs for read and write (
ReadPipe
andWritePipe
) rather than a single bi-directional pipe, something like below?
https://github.com/ueno/wasmtime/blob/wip/dueno/wasi-c2-virt/crates/wasi-c2/src/virt/pipe.rs#L375
sunfishcode submitted PR Review.
sunfishcode created PR Review Comment:
From my perspective, the granularity of various traits in this area is something we're still figuring out. Could you say more about why
Pipe
in your link here usesSeek
? Elsewhere you mentioned using TCP, QUIC, etc. sockets, however they don't supportSeek
. Things that do implementSeek
such as files and memory buffers aren't interactive and don't make sense for interactive protocols, which is what one typically does on top of TCP, QUIC, etc. sockets.
pchickey submitted PR Review.
pchickey created PR Review Comment:
The use case we wrote ReadPipe and WritePipe for is just to buffering stdin and stdout/err for an instance, rather than communicate between instances. Bi-directional communication is more complex and something I wasn't ready to bite off yet.
ueno submitted PR Review.
ueno created PR Review Comment:
Could you say more about why Pipe in your link here uses Seek? Elsewhere you mentioned using TCP, QUIC, etc. sockets, however they don't support Seek.
Yes, that's true; I added it just for my demo of the other branch. On the other hand, I suspect Seek will be desirable in the case with running Wasm programs in TEE, to support transparent encryption of files.
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
sunfishcode submitted PR Review.
sunfishcode created PR Review Comment:
system-interface has this in
num_ready_bytes
. One difference from how wasi-common does it is that system-interface will sometimes return 0 if the underlying device can't report how many bytes it can read. Here, since we just calledpoll
and it told us that something was ready, we should dolet n = sub.num_ready_bytes()
and thenmax(n, 1)
.
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey submitted PR Review.
pchickey created PR Review Comment:
Fixed now- thanks!
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey has marked PR #2487 as ready for review.
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
WIP
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
The
WasiFile
andWasiDir
traitsTraits for the rest of WASI's features
The
cap-std-sync
implementation of the WASI traitsImproving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
The
WasiFile
andWasiDir
traitsTraits for the rest of WASI's features
The
cap-std-sync
implementation of the WASI traitsImproving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types.Traits for the rest of WASI's features
Snapshot architecture
The
cap-std-sync
implementation of the WASI traitsImproving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR)Traits for the rest of WASI's features
Snapshot architecture
The
cap-std-sync
implementation of the WASI traitsImproving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows- [ ] Yeet the virtfs out to a separate PR
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR)Traits for the rest of WASI's features
Snapshot architecture
The
cap-std-sync
implementation of the WASI traitsImproving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows- [ ] Yeet the virtfs out to a separate PR
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR)Traits for the rest of WASI's features
Snapshot architecture
The
cap-std-sync
implementation of the WASI traitsImproving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows- [ ] Yeet the virtfs out to a separate PR
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
cap-std-sync
implementation of the WASI traitsImproving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows- [ ] Yeet the virtfs out to a separate PR
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
cap-std-sync
implementation of the WASI traitsImproving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows- [ ] Yeet the virtfs out to a separate PR
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
cap-std-sync
implementation of the WASI traitsWhy is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon!Improving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows- [ ] Yeet the virtfs out to a separate PR
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
cap-std-sync
implementation of the WASI traitsWhy is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows- [ ] Yeet the virtfs out to a separate PR
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
Wasi-common's test suite lives at
crates/test-programs
.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows- [ ] Yeet the virtfs out to a separate PR
<!--
Please ensure that the following steps are all taken care of before submitting
the PR.
[ ] This has been discussed in issue #..., or if not, please tell us why
here.[ ] A short description of what this does, why it is needed; if the
description becomes long, the matter should probably be discussed in an issue
first.[ ] This PR contains test cases, if meaningful.
- [ ] A reviewer from the core maintainer team has been assigned for this PR.
If you don't know who could review this, please indicate so. The list of
suggested reviewers on the right can help you.Please ensure all communication adheres to the code of conduct.
-->
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.Changes to
wiggle-wasmtime
and dependentsChanges to
wasmtime-wasi
Regressions
Some behavior around trailing slashes in paths has changed from the test suite. We expect there are some improvements we'll make to these corner cases after this PR lands.
For now, the
path_rename_file_trailing_slashes
andremove_directory_trailing_slashes
tests are#[ignore]
'd on all platforms, and additionally theinteresting_paths
test is ignored on Windows.Additionally, some behavior around the
FdFlags::{SYNC, DSYNC, RSYNC}
flags have changed. For now, cap-std does not support opening a file with these flags. Using these flags will result in anErrno::NOTSUP
(Not supported).Outstanding issues required to merge this PR:
- [ ] Metadata not associated with open file panics on windows: https://github.com/bytecodealliance/cap-std/issues/142
- [ ]
DirExt::delete_file_or_symlink
forsymlink_create
test to pass on Windows- [ ] Yeet the virtfs into a separate PR
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate. This PR will only land with support for testingwasi-cap-std-sync
, but it will be easy to add more runtimes undertests/wasm_tests/runtime/
as more impls are created, with a minimum of boilerplate inbuild.rs
.Changes to
wiggle-wasmtime
and dependentsYou used to pass a
WasiCtx
(or whatever ctx type) directly to theWasi
struct generated bywiggle-wasmtime
, and the generated code would wrap the ctx into aRc<RefCell<ctx>>
. This got in the way of supporting multiple snapshots simultaneously, so now callers of the generated code have to pass in anRc<RefCell<ctx>>
.I made mechanical changes to
wasi-nn
(cc @abrown) andwasi-crypto
(cc @jedisct1) to accommodate these changes. This was of particular help to thewasi-crypto
code - I was able to erase an entire Rc<> indirection by getting wiggle out of our way. Sorry that I did not take the time to break this out into a standalone PR.Changes to
wasmtime-wasi
wasmtime-wasi
now supports using multiple snapshots to interface to the sameWasiCtx
!
- `wasmtime_wa
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate. This PR will only land with support for testingwasi-cap-std-sync
, but it will be easy to add more runtimes undertests/wasm_tests/runtime/
as more impls are created, with a minimum of boilerplate inbuild.rs
.Changes to
wiggle-wasmtime
and dependentsYou used to pass a
WasiCtx
(or whatever ctx type) directly to theWasi
struct generated bywiggle-wasmtime
, and the generated code would wrap the ctx into aRc<RefCell<ctx>>
. This got in the way of supporting multiple snapshots simultaneously, so now callers of the generated code have to pass in anRc<RefCell<ctx>>
.I made mechanical changes to
wasi-nn
(cc @abrown) andwasi-crypto
(cc @jedisct1) to accommodate these changes. This was of particular help to thewasi-crypto
code - I was able to erase an entire Rc<> indirection by getting wiggle out of our way. Sorry that I did not take the time to break this out into a standalone PR.Changes to
wasmtime-wasi
wasmtime-wasi
now supports using multiple snapshots to interface to the sameWasiCtx
!
- `wasmtime_w
[message truncated]
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
wasi_common::ErrorKind
wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate. This PR will only land with support for testingwasi-cap-std-sync
, but it will be easy to add more runtimes undertests/wasm_tests/runtime/
as more impls are created, with a minimum of boilerplate inbuild.rs
.Changes to
wiggle-wasmtime
and dependentsYou used to pass a
WasiCtx
(or whatever ctx type) directly to theWasi
struct generated bywiggle-wasmtime
, and the generated code would wrap the ctx into aRc<RefCell<ctx>>
. This got in the way of supporting multiple snapshots simul
[message truncated]
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variantsIf you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate. This PR will only land with support for testingwasi-cap-std-sync
, but it will be easy to add more runtimes under `tests/wasm_
[message truncated]
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate. T
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
jedisct1 submitted PR Review.
jedisct1 created PR Review Comment:
Incrementing the key is a very good thing; it helps avoid reuse and catch bugs (and we don't have to deal with
select(2)
).But why not wrap on overflow? If entries are properly closed after use, there wouldn't be anything wrong with that, especially since the map is checked right after (even though it is not necessary before a wrap).
jedisct1 submitted PR Review.
jedisct1 created PR Review Comment:
What are the thread-safety guaranty requirements?
Couldn't multiple threads access the same key concurrently?
Instead of
Any
, wouldn't it be safer to enforceAny + Send + Sync
?
pchickey submitted PR Review.
pchickey created PR Review Comment:
A
Table
should only be associated with a singlewasmtime::Store
, which is not Send or Sync. So, I made no attempt to provide any thread-safety guarantees.
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey submitted PR Review.
pchickey created PR Review Comment:
Thanks, I fixed this to wrap on overflow, and only trap when the table is full.
jedisct1 submitted PR Review.
jedisct1 created PR Review Comment:
Are descriptors 0/1/2 counted here?
jedisct1 submitted PR Review.
jedisct1 created PR Review Comment:
As a side note, it may be useful to:
- Have a way to set an upper limit to the number of entries
- Have a way to get the current set of keys in the table, or at least the count. This is super useful in order to debug descriptor leaks (not just in hostcalls, also in applications).
pchickey submitted PR Review.
pchickey created PR Review Comment:
The ctx constructor asserts that descriptors 0/1/2 are populated, so I believe they are counted, though in a different spot.
I agree those features sound useful, but I think they're out of scope for landing the initial version of this.
jedisct1 submitted PR Review.
jedisct1 created PR Review Comment:
So a handle will never be shared by multiple threads?
Is this a requirement of the WebAssembly threading proposal, or a temporary limitation in Wasmtime?
More generally, should hostcalls assume that a resource will never be shared?
pchickey submitted PR Review.
pchickey created PR Review Comment:
Right, a handle will never be shared between threads. It is a limitation of Wasmtime until we choose to implement a threading proposal.
If a hostcall needs to assume a resource is shared between multiple Stores running in separate threads, it can do its own internal arc/mutex wrapping inside the resource.
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate. T
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate. T
[message truncated]
pchickey edited PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate. T
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
pchickey requested sunfishcode for a review on PR #2487.
pchickey updated PR #2487 from pch/wasi_common_cap_std
to main
:
This PR is a complete rewrite of the
wasi-common
crate. It uses @sunfishcode 's newcap-std
family of crates to provide a sandboxed implementation of WASI on the local filesystem.Note that this is a breaking change for all users of WASI with Wasmtime, except for the C API.
Re-architecting
wasi-common
Over the past year or so, we've run up against many design problems in
wasi-common
. Many of these problems ended up being so fundamental that a rewrite, as prolonged as it was, ended up being more tractable than incremental changes.The
Table
wasi-common
now has aTable
type that is designed to map u32 handles to resources. The table is now part of the public interface to aWasiCtx
- it is reference counted so that it can be shared beyond aWasiCtx
with other WASI proposals (e.g.wasi-crypto
andwasi-nn
) to manage their resources. Elements in theTable
areAny
typed.The
Table
type is intended to model how the Interface Types concept of Resources is shaping up. Right now it is just an approximation.The
WasiFile
andWasiDir
traitsThe WASI specification only defines one
handle
type,fd
, on which all operations on both files and directories (aka dirfds) are defined. We believe this is a design mistake, and are architecting wasi-common to make this straightforward to correct in future snapshots of WASI. Wasi-common internally treats files and directories as two distinct resource types in the table -Box<dyn WasiFile>
andBox<dyn WasiDir>
. The snapshot 0 and 1 interfaces viafd
will attempt to downcast a table element to one or both of these interfaces depending on what is appropriate - e.g.fd_close
operates on both files and directories,fd_read
only operates on files, andfd_readdir
only operates on directories.The
WasiFile
andWasiDir
traits are defined bywasi-common
in terms of types defined directly in the crate's source code (I decided it should NOT those generated by thewiggle
proc macros, see snapshot architecture below), as well as thecap_std::time
family of types. And, importantly,wasi-common
itself provides no implementation ofWasiDir
, and only two trivial implementations ofWasiFile
on thecrate::pipe::{ReadPipe, WritePipe}
types, which in turn just delegate tostd::io::{Read, Write}
. In order forwasi-common
to access the local filesystem at all, you need to provideWasiFile
andWasiDir
impls through either the newwasi-cap-std-sync
crate found atcrates/wasi-common/cap-std-sync
- see the section on that crate below - or by providing your own implementation from elsewhere.This design makes it possible for
wasi-common
embedders to statically reason about access to the local filesystem by examining what impls are linked into an application. We found that this separation of concerns also makes it pretty enjoyable to write alternative implementations, e.g. a virtual filesystem (which will land in a future PR).Traits for the rest of WASI's features
Other aspects of a WASI implementation are not yet considered resources and accessed by
handle
. We plan to correct this design deficiency in WASI in the future, but for now we have designed the following traits to provide embedders with the same sort of implementation flexibility they get with WasiFile/WasiDir:
- Timekeeping:
clocks::WasiSystemClock
andclock::WasiMonotonicClock
provide the two interfaces for a clock.WasiSystemClock
represents time as acap_std::time::SystemTime
, andWasiMonotonicClock
represents time ascap_std::time::Instant
.- Randomness: we re-use the
cap_rand::RngCore
trait to represent a randomness source. A trivialDeterministic
impl is provided.- Scheduling: The
WasiSched
trait abstracts over thesched_yield
andpoll_oneoff
functions.Users can provide implementations of each of these interfaces to the
WasiCtx::builder(...)
function. Thewasi_cap_std_sync::WasiCtxBuilder::new()
function uses this public interface to plug in its own implementations of each of these resources.Snapshot architecture
One goal we've had for a while, but not quite met, is for multiple WASI snapshots to provide an interface to the same underlying
WasiCtx
. This provides us a path to evolve WASI by allowing the same WASI Command to import functions from different snapshots - e.g. the user could use Rust'sstd
which imports snapshot 1, but also depend directly on thewasi
crate which imports some future snapshot 2. Right now, this amounts to supporting snapshot 1 and "snapshot 0" aka wasi_unstable at once.The architectural rules for snapshots are:
- Snapshots are arranged into modules under
crate::snapshots::
.- Each snapshot should invoke
wiggle::from_witx!
withctx: crate::WasiCtx
in its module, and impl all of the required traits.- Snapshots can be implemented in terms of other snapshots. For example, snapshot 0 is mostly implemented by calling the snapshot 1 implementation, and converting its own types back and forth with the snapshot 1 types. In a few cases, that is not feasible, so snapshot 0 carries its own implementations in terms of the
WasiFile
andWasiSched
traits.- Snapshots can be implemented in terms of the
Wasi*
traits given byWasiCtx
. No further downcasting via theas_any
escape hatch is permitted.The
wasi_common::Error
type
wasi_common::Error
is nowanyhow::Error
.wasi_common::snapshots::preview_1
contains all of the logic for transforming anError
into anErrno
, by downcasting the error into any of
std::io::Error
- these are thrown bystd
,cap_std
, etc for most of the operations WASI is concerned with.wasi_common::ErrorKind
- these are a subset of the Errnos, and are constructed directly by wasi-common or an impl rather than coming from the OS or some library which doesn't know about WASI.wiggle::GuestError
std::num::TryFromIntError
std::str::Utf8Error
and then applying specialized logic to translate each of those intoErrno
s.The
wasi_common::ErrorExt
trait provides human-friendly constructors for thewasi_common::ErrorKind
variants .If you throw an error that does not downcast to one of those, it will turn into a
wiggle::Trap
and terminate execution.The real value of using
anyhow::Error
here is being able to useanyhow::Result::context
to aid in debugging of errors.The
wasi-cap-std-sync
implementation of the WASI traitsThe
wasi-cap-std-sync
crate provides impl ofWasiFile
andWasiDir
in terms ofcap_std::fs::{File, Dir}
. These types provide sandboxed access to the local filesystem on both Unix and Windows.The entire design story of
cap-std
is much bigger than we can address here, but in short, its functionality replaces all of thewasi_common::sys
hierarchy, as well as theyanix
/winx
crates. All syscalls are hidden behind thecap-std
hierarchy, with the lone exception of thesched
implementation, which is provided for both unix and windows in separate modules.Any
wasi_common::{WasiCtx, WasiCtxBuilder}
is interoperable with thewasi-cap-std-sync
crate. However, for convenience,wasi-cap-std-sync
provides its ownWasiCtxBuilder
that hooks up to all of the crate's components, i.e. it fills in all of the arguments toWasiCtx::builder(...)
, presentspreopen_dir
in terms ofcap_std::fs::Dir
, and provides convenience methods for inheriting the parent process's stdio, args, and env.The only place we expect to run into long-term compatibility issues between
wasi-cap-std-sync
and the other impl crates that will come later is in theSched
abstraction. Once we can build an async scheduler based on RustFuture
s, async impls will be able to interoperate, but the synchronous scheduler depends on downcasting theWasiFile
type down to concrete types it knows about (which in turn implAsRawFd
for passing to unixpoll
, or the analogous traits on windows).Why is this impl suffixed with
-sync
? https://github.com/bytecodealliance/wasmtime/pull/2434 async is coming soon! The async impl may end up depending on tokio or other relatively heavy deps, so we will retain a sync implementation so that wasi-common users have an option of not pulling in an async runtime.Improving the WASI test suite
The bulk of
wasi-common
's test suite lives atcrates/test-programs
. This test suite was extremely useful for guiding this rewrite. We improved the test suite in numerous ways, including
- Breaking tests out into smaller units, so that failing behavior can be isolated more easily
- Introducing a scheme which allows the test runner to describe to the wasm code what behaviors to expect of the embedding. Behaviors which vary between platforms (e.g.
fd_allcoate
is impossible to faithfully implement on Windows and is not provided by MacOS) are communicated to the guest by environment variables, which in turn is available in the guest behind the globalTESTCONFIG
struct.- Introducing the
assert_errno!
macro, which pretty-prints errnos by name rather than number in the error message.assert_errno!
integrates withTESTCONFIG
to specify which errno is expected on which platform. This allows the test source to describe the full set of acceptable errnos a call may return (all possible errnos will be acceptable if noERRNO_MODE_*
env var is set), and also detect regressions on any given platform.- We still use
crates/test-platforms/build.rs
to generate the test suite, and use functions directly inbuild.rs
to describe theTESTCONFIG
expectations, as well as which tests are to be ignored (expected to fail due to regressions) on what platforms.- The test suite has been generalized to support multiple backends to the
wasi-common
crate.
[message truncated]
sunfishcode submitted PR Review.
sunfishcode submitted PR Review.
sunfishcode created PR Review Comment:
Is this line still needed?
sunfishcode created PR Review Comment:
Are these
fail-fast: false
lines still needed?
sunfishcode deleted PR Review Comment.
sunfishcode deleted PR Review Comment.
pchickey merged PR #2487.
Last updated: Dec 23 2024 at 12:05 UTC