-
Notifications
You must be signed in to change notification settings - Fork 666
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 process_vm_readv and process_vm_writev #568
Conversation
Opened too soon - I guess I should add both a platform conditional and some tests. Let me do that. |
One design-ish question: these syscalls take a |
7632f2a
to
5dee86a
Compare
For some reason I thought I did this back when rust-lang/libc#283 was filed for https://github.com/jvns/ruby-stacktrace. Anyway, thanks for doing this! Re the I prefer the empty flags arg since the ergonomics aren't that bad, and these aren't super frequently used functions. The alternative may at some point down the line force a major version bump on all users just to correctly handle these infrequently used functions. |
Good point about a major-version bump for an obscure function. I've added a flags type. I wasn't really sure what to name it since no constants exist yet, but my current best guess is Adding an empty |
@alexcrichton thoughts on this for bitflags?
|
@geofft re the name of the flag type, I think we can go with more or less anything since we can avoid breaking changes by adding a type alias if / when something actually exists. What do you think? |
Oh yes we'd certainly be interested in a fix! |
@kamalmarhubi Oh good call, that sounds forwards-compatible. nix is on bitflags 0.7.0, and upstream is on 0.8.0 which has a few changes. Can we merge this as is and I'll send in a patch to bitflags + a cleanup for nix at some point in the future? |
☔ The latest upstream changes (presumably #536) made this pull request unmergeable. Please resolve the merge conflicts. |
@geofft sorry for the delay. I'd absolutely be ok to merge this and fix up the bitflag later. Nice trick with |
(This needs a rebase though!) |
Tests are failing on ARM only with "qemu: Unsupported syscall: 376" (or 270 on aarch64). These are the right syscall numbers. Is there a way to mark this as a Travis-specific false positive? I would expect the code to work on actual ARM (although I suppose I should dig out a device). If we can't ignore this from Travis easily, I'm happy to |
We do need a system to handle when Qemu on Travis isn't able to test features. We need a way to disable them only when testing on CI (I think ideally we could detect the CI environment variable to disable it). I'd also like to have any such issues filed upstream so that we can have a comment by ever disabled test with a URL for the tracking issue so we will be able to easily turn the test on once the feature is added. |
This adds `--cfg=travis` to builds under CI, allowing tests to be conditionally ignored by marking them with #[cfg_attr(travis, ignore)] refs nix-rust#568
If #588 makes sense to at least a couple of maintainers, it'll be a way to ignore these tests in Travis. (I'm assuming they pass locally on a reals system.) |
@kamalmarhubi What do you think about whenever we remove a test from running on Travis that we have a link to an upstream issue if one exists? |
5c8d49f
to
3a55a7a
Compare
OK, I tried both |
cc3897b
to
25e71ad
Compare
Yeah, I saw the discussion on #590 - I'm trying a few things to see if they work while we wait for cross to get upgraded, and I'll comment there if they do. |
☔ The latest upstream changes (presumably ba5c837) made this pull request unmergeable. Please resolve the merge conflicts. |
@geofft Are you still interested in merging this PR? |
dcccf7b
to
9d1bfbc
Compare
@Susurrus - rebased, sorry! The libc crate doesn't define these functions on Android, so I've left them as normal-Linux-only for now,. (I'm guessing this is because Bionic only gained wrappers for these syscalls in Android 6.0 / API level 23, which is way newer than rustc's target of Android 2.3 / API level 9.) I did a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly minor changes, primarily remove the Flags
argument and rework the test to not fork
as that will deadlock tests every so often.
src/sys/uio.rs
Outdated
@@ -56,6 +59,38 @@ pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{ | |||
Errno::result(res).map(|r| r as usize) | |||
} | |||
|
|||
// process_vm_{read,write}v currently doesn't use flags, but we define this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flags should always be zero in my current version of Linux. I don't think forward compatibility here is a concern because as soon as they're flags we have issues with backwards compatibility on the systems themselves. Let's just leave all this extra boilerplate off for now for the sake of a cleaner API. By the time new flags are added it could be years.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the earlier discussion on the PR - I'm pretty indifferent here, @kamalmarhubi expressed a preference to just add the flags argument now. I agree that probably there will never be flags.
I guess the other option is that we just break names from libc slightly (which we do in other places) and add a four-parameter process_vm_readv_flags(pid, local_iov, remote_iov, flags)
if we ever need to, which avoids the API break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove flags. We can assess a breaking change or adding *_flags
when/if this moment comes to pass in the future.
src/sys/uio.rs
Outdated
); | ||
|
||
#[cfg(any(target_os = "linux"))] | ||
pub fn process_vm_writev(pid: Pid, local_iov: &[IoVec<&[u8]>], remote_iov: &mut [IoVec<&mut [u8]>], flags: CmaFlags) -> Result<usize> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These needs docs. See some of the recently closed PRs for an idea of what we're looking for. I think these are Linux-specific functions, so you should link to a manpage on man7.org in the doc comment. Please run cargo doc --no-deps --open
and read through the generated docs to make sure they look nice as part of your testing.
src/sys/uio.rs
Outdated
} | ||
|
||
#[cfg(any(target_os = "linux"))] | ||
pub fn process_vm_readv(pid: Pid, local_iov: &mut [IoVec<&mut [u8]>], remote_iov: &[IoVec<&[u8]>], flags: CmaFlags) -> Result<usize> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also needs docs.
src/sys/uio.rs
Outdated
Errno::result(res).map(|r| r as usize) | ||
} | ||
|
||
#[cfg(any(target_os = "linux"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the any(
src/sys/uio.rs
Outdated
} | ||
); | ||
|
||
#[cfg(any(target_os = "linux"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the any(
src/sys/uio.rs
Outdated
pub fn process_vm_readv(pid: Pid, local_iov: &mut [IoVec<&mut [u8]>], remote_iov: &[IoVec<&[u8]>], flags: CmaFlags) -> Result<usize> { | ||
let res = unsafe { | ||
libc::process_vm_readv(pid.into(), local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong, | ||
remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, flags.bits()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This indentation is wrong, it should be aligned to pid
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I'll add a linebreak before local_iov. (Should I be using rustfmt or something?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't recommend rustfmt as it'll probably change everything in the file and its style changes are also not stable. I used to use it for my own libs, but I don't anymore because of it. I think continuing to do this manually is fine.
test/sys/test_uio.rs
Outdated
@@ -190,3 +190,51 @@ fn test_preadv() { | |||
let all = buffers.concat(); | |||
assert_eq!(all, expected); | |||
} | |||
|
|||
#[test] | |||
#[cfg(any(target_os = "linux", target_os = "android"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the android
here.
test/sys/test_uio.rs
Outdated
use std::{str, slice}; | ||
|
||
let (r, w) = pipe().unwrap(); | ||
match fork() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forking is bad within the Rust test harness as it can cause deadlocks. Any other way you can implement this test? Also some comments in here explaining things for those unfamiliar with the code would be nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The child calls pause()
, which means it never continues execution past that point, so it doesn't unwind anything and shouldn't cause any deadlocks in execution. If you're having trouble with deadlocks during child creation then yeah that's a problem but also that seems surprising... I guess another thread might be holding the malloc lock or something? Blah.
I can probably use process_vm_readv(getpid()...)
with a static string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't fully understand the problem, @asomers is our resident expert, so I'll let him chime in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the fork-related deadlocks that I've seen so far happen as the child returns from the test function. So if the child truly never returns, then you should be ok. You'll still have to grab the FORK_MTX however, or you could cause the wait
tests to fail.
@asomers Can you chime in here about the use of |
Ugh, I had a moment of worry that using From |
487cd87
to
c84158f
Compare
@Susurrus all review comments addressed I think! There's a new |
1289d24
to
37fa931
Compare
test/sys/test_uio.rs
Outdated
}, | ||
Ok(Child) => { | ||
let _ = close(r); | ||
let s = String::from("test"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, you shouldn't use String::from
in the child, because that requires allocating memory, and memory allocation isn't async signal safe. The format!
macro probably does allocation too. See http://man7.org/linux/man-pages/man7/signal-safety.7.html .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@asomers Let me know if this looks better. (I'm not actually sure if it's fully safe, in the sense that I'm not sure there's a guarantee that the writes to memory actually happen, but at least it's not async-signal-unsafe.)
@kamalmarhubi This also touches on #305, which you filed. Could you comment here on the proposal here? |
@geofft Just wanted to ping you on this and see if we could get this wrapped up soon. |
@Susurrus Woops, I totally forgot that this hadn't landed (also I started a new job in August). What needs to be done here - just getting rid of memory allocation in the test's child process? I can update the PR to fix that, hopefully tonight. |
LGTM bors r+ |
No description provided.