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

Newtypes for uid_t, gid_t and pid_t. #629

Merged
merged 1 commit into from
Jul 4, 2017
Merged

Conversation

Kixunil
Copy link
Contributor

@Kixunil Kixunil commented Jun 24, 2017

No description provided.

Copy link
Member

@asomers asomers left a 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 {
Copy link
Member

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

Copy link
Contributor Author

@Kixunil Kixunil Jun 24, 2017

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?

Copy link
Member

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?

Copy link
Contributor Author

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 {
Copy link
Contributor

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?

Copy link
Contributor Author

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?)

Copy link
Contributor

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.

@Susurrus
Copy link
Contributor

Right now the ptrace* functions are broken because of #614. I'd like to see that fixed before this.

@Kixunil
Copy link
Contributor Author

Kixunil commented Jun 25, 2017

@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();
Copy link
Contributor

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).

Copy link
Contributor Author

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();
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

getpid can't fail.

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Contributor Author

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();
Copy link
Contributor

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 {
Copy link
Contributor

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 {
Copy link
Contributor

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 {
Copy link
Contributor

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
Copy link
Contributor

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)"

Copy link
Contributor Author

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.

@Susurrus Susurrus mentioned this pull request Jun 28, 2017
10 tasks
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
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed.

@asomers
Copy link
Member

asomers commented Jul 1, 2017

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.

@Kixunil
Copy link
Contributor Author

Kixunil commented Jul 1, 2017

Done. I don't like squashing because it wipes history, that's why I didn't squash until asked. :)

@Susurrus
Copy link
Contributor

Susurrus commented Jul 1, 2017

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.

@asomers
Copy link
Member

asomers commented Jul 2, 2017

@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?

@Kixunil
Copy link
Contributor Author

Kixunil commented Jul 2, 2017

Sorry about that, I don't squash commits often (I probably did it only once two years ago). I hope it's fine now.

@asomers
Copy link
Member

asomers commented Jul 2, 2017

bors r+

bors bot added a commit that referenced this pull request Jul 2, 2017
629: Newtypes for uid_t, gid_t and pid_t. r=asomers
@bors
Copy link
Contributor

bors bot commented Jul 2, 2017

Timed out

@asomers
Copy link
Member

asomers commented Jul 4, 2017

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+

bors bot added a commit that referenced this pull request Jul 4, 2017
629: Newtypes for uid_t, gid_t and pid_t. r=asomers
@asomers
Copy link
Member

asomers commented Jul 4, 2017

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.
buildbot/buildbot#3078

@bors
Copy link
Contributor

bors bot commented Jul 4, 2017

Timed out

@Kixunil
Copy link
Contributor Author

Kixunil commented Jul 4, 2017

because the author has a non-ascii character in his name

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.)

@asomers
Copy link
Member

asomers commented Jul 4, 2017

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants