-
Notifications
You must be signed in to change notification settings - Fork 665
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
Newtypes for uid_t, gid_t and pid_t. #629
Conversation
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 very much like this change. This sort of type safety is exactly the value that nix was meant to provide. But it does break backwards compatibility, so we need to be sure that our users know how to migrate their code. Could you please add an entry to CHANGELOG.md ?
src/unistd.rs
Outdated
geteuid() | ||
} | ||
|
||
pub fn is_root(self) -> bool { |
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 argument should be &self
so this method won't consume self
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.
Doesn't matter much, since it's Copy
, don't you think?
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.
In this case, you're right that is_root(self)
and is_root(&self)
are probably equivalent. But stylistically, the latter is preferred. In the entire Nix crate, we only use the former style in one place, and that's because a std trait requires it. The nonconsuming variety is also more future-proof. For example, we might someday turn these methods into a Trait, and implement it for other objects that are harder to clone, like SIDs. Are there any downsides to taking self
by reference?
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'm not aware of any downsides (apart from theoretical slow down, which should be optimized-out). I implemented it this way mostly because I didn't care, since it's Copy
. I understand the style and, I'm going to change it.
} | ||
} | ||
|
||
impl fmt::Display for Uid { |
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.
Can't you derive Display
for this type?
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.
AFAIK #[derive(Display)]
doesn't work (what code should Rust generate?)
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.
You're right, I was thinking of Debug
. I don't think we need to have Display
implemented for these types, but I'm not against it either.
Right now the |
@asomers Is that changelog entry OK for you? |
@@ -90,7 +91,7 @@ mod linux_android { | |||
|
|||
#[test] | |||
fn test_gettid() { | |||
let tid = gettid(); | |||
let tid: ::libc::pid_t = gettid().into(); |
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'm pretty certain this is always going to be > 0 (related to getpid
test above).
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.
Me too. I just wanted to keep test as they were.
@@ -78,8 +79,8 @@ fn test_mkstemp() { | |||
|
|||
#[test] | |||
fn test_getpid() { | |||
let pid = getpid(); | |||
let ppid = getppid(); | |||
let pid: ::libc::pid_t = getpid().into(); |
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.
Why doesn't getpid()
return a Result
instead of a Pid
regardless of success? That would be much more ergonomic then making the user have to cast into a libc
type just to check if the return value is valid.
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.
getpid
can't fail.
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.
You're right that it can't fail, but it can return 0. I meant to suggest using an Option<Pid>
type here rather than Result
. The thing is that the user shouldn't need to compare the Pid
to 0, that's should be something abstracted away by this newtype. So if the user gets a Pid
it should be valid, otherwise they should get a None
.
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 think the API is fine for normal use. The only reason for the cast is for the assertion. I don't think ordinary consumers of getpid
will ever need the cast.
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.
Something that we might improve later: use NonZero<T>
, once it's stabilized (I watch relevant issue and I think it's getting close.) So the compiler would optimize Option<Pid>
to Pid
.
The question is whether zero PID is somehow forbidden by POSIX.
@@ -21,7 +21,8 @@ fn test_fork_and_waitpid() { | |||
Ok(Child) => {} // ignore child here | |||
Ok(Parent { child }) => { | |||
// assert that child was created and pid > 0 | |||
assert!(child > 0); | |||
let child_raw: ::libc::pid_t = child.into(); |
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.
Again, it'd be great if we could make this check more ergonomic.
src/unistd.rs
Outdated
pub struct Uid(uid_t); | ||
|
||
impl Uid { | ||
pub fn from_raw(uid: uid_t) -> Self { |
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 of these methods needs doccomments.
src/unistd.rs
Outdated
pub struct Gid(gid_t); | ||
|
||
impl Gid { | ||
pub fn from_raw(gid: gid_t) -> Self { |
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.
Again, doccomments for these methods please.
src/unistd.rs
Outdated
pub struct Pid(pid_t); | ||
|
||
impl Pid { | ||
pub fn from_raw(pid: pid_t) -> Self { |
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.
doc comments here as well.
CHANGELOG.md
Outdated
@@ -32,6 +32,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). | |||
- Changed type signature of `sys::select::FdSet::contains` to make `self` | |||
immutable ([#564](https://github.com/nix-rust/nix/pull/564)) | |||
- Changed type of `sched::sched_setaffinity`'s `pid` argument to `pid_t` | |||
- Newtypes for UID, GID, and PID. `uid_t` changed to `Uid`, `gid_t` changed to |
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.
Please link to the pull request like the other changelog entries do. Additionally I'd rephrase this to be: "Introduced wrapper types for gid_t
, pid_t
, and uid_t
as Gid
, Pid
, and Uid
respectively. Various functions have been changed to use these new types as arguments. (PULL_REQUEST_LINK)"
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.
OK, I did as you suggested.
src/unistd.rs
Outdated
|
||
/// Returns true if the `Uid` represents privileged user - root. (If it equals zero.) | ||
pub fn is_root(&self) -> bool { | ||
self.0 == 0 |
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.
if you're going to define a ROOT
constant, then you should use it here.
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.
Good point. I'll look into it.
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.
Changed.
It all looks good to me. The last step is to squash your commits. BTW, thanks for not squashing them until now; it's easier to review the unsquashed changes. |
Done. I don't like squashing because it wipes history, that's why I didn't squash until asked. :) |
Yeah, GitHub's interface is terrible about tracking revisions to things. I much prefer GitLab's interface for PRs where it will keep every revision, squashed or not, and let you see how things changed. Makes it nice to not have these final "alright now squash everything" discussions. |
@Kixunil even though you squashed the commits, you didn't fixup the commit message. The commit message still describes changes between revisions that no longer exist. Could you please clean up the wording? |
Sorry about that, I don't squash commits often (I probably did it only once two years ago). I hope it's fine now. |
bors r+ |
Timed out |
I'm not sure, but I think that buildbot might timeout when bors does a branch rename instead of a merge commit. If that's true, then this shouldn't timeout a second time, because there have been commits in the meantime. bors r+ |
Ok, I figured it out. Buildbot isn't building the merge commit because the author has a non-ascii character in his name, and buildbot 0.9.5 has an issue with that. I'll wait until Bors times out again, then I'll merge this PR manually. |
Timed out |
Ouch, is this issue specific for the buildbot or are non-ASCII names non-standard/forbidden in git author names? (I've never had a problem with it until now.) |
@Kixunil it's a bug in BuildBot, and it's already fixed upstream. I just haven't upgraded our buildbot server to that version yet. For now, I'm going to bypass bors and merge directly. |
No description provided.