Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🕳 Add virtual pipes to wasi-common #1949

Merged
merged 2 commits into from
Jul 1, 2020
Merged

🕳 Add virtual pipes to wasi-common #1949

merged 2 commits into from
Jul 1, 2020

Conversation

acfoltzer
Copy link
Collaborator

This introduces Handle implementations for readable and writable pipes, backed by arbitrary Read and Write types, respectively. In particular, this allows for easily providing, capturing, or redirecting WASI stdio without having to resort to OS-provided file descriptors.

The implementation is based heavily on wasi_common::virtfs::InMemoryFile, but without inapplicable operations like seek or allocate.

Note that these types are not 1:1 replacements for real pipes, because they do not support poll_oneoff.

This introduces `Handle` implementations for readable and writable pipes, backed by arbitrary `Read`
and `Write` types, respectively. In particular, this allows for easily providing, capturing, or
redirecting WASI stdio without having to resort to OS-provided file descriptors.

The implementation is based heavily on `wasi_common::virtfs::InMemoryFile`, but without inapplicable
operations like `seek` or `allocate`.

Note that these types are not 1:1 replacements for real pipes, because they do not support `poll_oneoff`.
@github-actions github-actions bot added the wasi Issues pertaining to WASI label Jun 30, 2020
@github-actions
Copy link

Subscribe to Label Action

cc @kubkon

This issue or pull request has been labeled: "wasi"

Thus the following users have been cc'd because of the following labels:

  • kubkon: wasi

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

Copy link
Collaborator

@iximeow iximeow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 exciting! Just a few small comments.

}
}

impl From<&[u8]> for ReadPipe<io::Cursor<Vec<u8>>> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
impl From<&[u8]> for ReadPipe<io::Cursor<Vec<u8>>> {
impl<'a> From<&'a [u8]> for ReadPipe<io::Cursor<&'a [u8]>> {

I think this is a correct way to spell an impl entirely on a ref of the underlying data, and I'm pretty sure we can Cursor<&'_ [u8]> for reading here, so this ought to let is avoid forcing a copy of the underlying slice?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly &'a [u8] is not Any due to the non-static lifetime, but Any is required to implement Handle 😭

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh drat.

}
}

impl From<&str> for ReadPipe<io::Cursor<String>> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same idea about a Cursor<&'a str> here too, but I'm not as sure that this'll Just Work. Might be worth trying?

}

fn fdstat_set_flags(&self, _fdflags: types::Fdflags) -> Result<()> {
// do nothing for now
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I punted on when first doing virtfs work was figuring out what kind of errors are actually acceptable to return from what function. I broadly worked off of In the parts of WASI which do correspond to POSIX functionality, WASI follows POSIX when it doesn't conflict with WASI's other goals. And, we consult POSIX even when we aren't strictly following it. from DesignPrinciples.md but we should probably consider documenting the full set of errors that WASI functions may return - even if that's simply "all functions may return any Errno" (I think we can and should do better than that, since it would be good to be accurate in communicating kinds of errors to downstream users)

I bring this up mostly because I'm wondering if it's right to accept and do nothing here, or should this Errno::Perm? Silently doing nothing is probably the right answer, but there ought to be more implementation guidance for virtfs users.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does POSIX do if you try to set O_APPEND on a pipe? Do real-world implementations support O_NONBLOCK on pipes? I don't have a clear sense of the right thing to do here yet.

I agree that we eventually want to move toward documenting the possible error codes for each function. I expect that'll be easier to do once we can start splitting up "file descriptors" into separate types, and we can have separate errno enums rather than one big POSIX-style errno space shared by filesystem and networking functions of all kinds.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that there should be more implementation guidance, but since I'm new to this corner of the codebase I'm not sure what to provide. Would you be okay with merging this for now with the expectation of doing that work later?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does POSIX do if you try to set O_APPEND on a pipe? Do real-world implementations support O_NONBLOCK on pipes? I don't have a clear sense of the right thing to do here yet.

I was actually really curious about this and how I'd find the answer: it turns out Linux source is a pretty clear answer - looks like O_APPEND and O_NONBLOCK would be accepted without issue. I didn't see anything in particular about fcntl's interaction with pipes in POSIX either, so I assume the flags should do the things they say they do? Where O_APPEND is functionally ignored on pipes, of course :)

Personally merging this as-is and providing better implementation guidance independently is exactly the approach I think we ought to take.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @sunfishcode, Github wasn't showing your comment in this thread when I left my reply. In my testing, O_APPEND seems to be ignored.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as long as you're ok making subtle behavior changes later :-).

crates/wasi-common/src/virtfs/pipe.rs Outdated Show resolved Hide resolved
crates/wasi-common/src/virtfs/pipe.rs Show resolved Hide resolved
crates/wasi-common/src/virtfs/pipe.rs Show resolved Hide resolved
crates/wasi-common/src/virtfs/pipe.rs Outdated Show resolved Hide resolved
crates/wasi-common/src/virtfs/pipe.rs Show resolved Hide resolved
crates/wasi-common/src/virtfs/pipe.rs Outdated Show resolved Hide resolved
@acfoltzer acfoltzer added the wasi:impl Issues pertaining to WASI implementation in Wasmtime label Jun 30, 2020

fn unlink_file(&self, _path: &str) -> Result<()> {
Err(Errno::Notdir)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Along the lines above, splitting up file descriptors into different types should also reduce the one-big-trait factor here, which should clean a lot of this up.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was actually thinking about breaking up Handle, but since this part of the code is new to me I didn't want to stir things up too much. Are you alright with saving this for a future PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I should have clarified; I'm talking about cleanups we can do in the future here.

@sunfishcode
Copy link
Member

I'm looking forward to the point where we can say that features like this should be implemented through link-time virtualization mechanisms, rather than traits in Wasmtime, but we're not there yet :-), so this overall looks good for now.

Copy link
Contributor

@pchickey pchickey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@acfoltzer acfoltzer merged commit 4f16f0d into main Jul 1, 2020
@acfoltzer acfoltzer deleted the acf/virtual-pipes branch July 1, 2020 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wasi:impl Issues pertaining to WASI implementation in Wasmtime wasi Issues pertaining to WASI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants