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

pty: Add forkpty #1042

Merged
merged 1 commit into from
Apr 23, 2019
Merged

pty: Add forkpty #1042

merged 1 commit into from
Apr 23, 2019

Conversation

kkuehlz
Copy link
Contributor

@kkuehlz kkuehlz commented Apr 9, 2019

No description provided.

@kkuehlz
Copy link
Contributor Author

kkuehlz commented Apr 9, 2019

Note: forkpty re-added to linux in rust-lang/libc#1313

@kkuehlz kkuehlz force-pushed the forkpty branch 2 times, most recently from 94bf05f to e0f1a90 Compare April 9, 2019 20:48
@kkuehlz
Copy link
Contributor Author

kkuehlz commented Apr 9, 2019

Err... failed CI for OSX but it passed all the tests?

@asomers
Copy link
Member

asomers commented Apr 9, 2019

It hung on OSX. Probably a bug in test_forkpty. It also appears to be hanging on FreeBSD. I'll terminate it.

@kkuehlz
Copy link
Contributor Author

kkuehlz commented Apr 10, 2019

@asomers yeah... i think i relied on linux kernel for how it handles a read after write. will fix in a bit.

@kkuehlz kkuehlz force-pushed the forkpty branch 2 times, most recently from 648b81d to 67688aa Compare April 10, 2019 22:58
@kkuehlz
Copy link
Contributor Author

kkuehlz commented Apr 11, 2019

@asomers Got CI passing. Can you take a look

Child => {
write(0, string.as_bytes()).unwrap();
pause(); // we need the child to stay alive until the parent calls read
},
Copy link
Member

Choose a reason for hiding this comment

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

In a Rust test, you cannot return from a forked child. That can cause deadlocks. Instead, you must _exit(0). The SIGTERM will probably suffice, but I would _exit(0) just in case.

src/pty.rs Outdated
/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
/// terminal settings of the slave will be set to the values in `termios`.
#[inline]
pub fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<ForkptyResult> {
Copy link
Member

Choose a reason for hiding this comment

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

80 cols, please.

src/pty.rs Outdated
/// If `winsize` is not `None`, the window size of the slave will be set to
/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
/// terminal settings of the slave will be set to the values in `termios`.
#[inline]
Copy link
Member

Choose a reason for hiding this comment

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

Why inline such a big function? In fact, it's rarely a good idea to use #[inline] at all. Better to let the compiler decide.

src/pty.rs Outdated

let mut master: libc::c_int = unsafe { mem::uninitialized() };
let res = {
match (termios.into(), winsize.into()) {
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 you could considerably shorten this block by using something like termios.into().unwrap_or(ptr::null_mut()).

src/pty.rs Outdated
/// This is returned by `forkpty`. Note that this type does *not* implement `Drop`, so the user
/// must manually close the file descriptors.
#[derive(Clone, Copy)]
#[allow(missing_debug_implementations)]
Copy link
Member

Choose a reason for hiding this comment

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

Why not derive Debug?

Copy link
Member

Choose a reason for hiding this comment

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

Now that you've derived Debug, you should remove the #[allow(missing_debug_implementations)]

test/test_pty.rs Outdated
let pty = forkpty(None, None).unwrap();
match pty.fork_result {
Child => {
write(0, string.as_bytes()).unwrap();
Copy link
Member

Choose a reason for hiding this comment

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

Yikes! Can you eliminate that magic number?

@kkuehlz
Copy link
Contributor Author

kkuehlz commented Apr 11, 2019

@asomers Made the suggested changes.

src/pty.rs Outdated
/// This is returned by `forkpty`. Note that this type does *not* implement `Drop`, so the user
/// must manually close the file descriptors.
#[derive(Clone, Copy)]
#[allow(missing_debug_implementations)]
Copy link
Member

Choose a reason for hiding this comment

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

Now that you've derived Debug, you should remove the #[allow(missing_debug_implementations)]

src/pty.rs Outdated
None => ptr::null_mut(),
};

let win = match winsize.into() {
Copy link
Member

Choose a reason for hiding this comment

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

FYI, instead of match winsize.into() you could equivalently do winsize.into().map(|ws| ws as *const Winsize).unwrap_or(ptr::null_mut()). It's just a matter of which style you prefer. Either is acceptable.

@kkuehlz
Copy link
Contributor Author

kkuehlz commented Apr 14, 2019

@asomers Thanks for the comments. I made the changes. Since the initial code was based largely off of openpty a lot of the review comments could be applied to that function; I am happy to make another PR to refactor that.

@kkuehlz
Copy link
Contributor Author

kkuehlz commented Apr 21, 2019

@asomers anything left to fix for this?


Ok(ForkptyResult {
master: master,
fork_result: fork_result,
Copy link
Member

Choose a reason for hiding this comment

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

If libc::forkpty fails, then master will be uninitialized here. For that matter, the return value will be wrong, too. You should ensure that it returns Err if libc::forkpty fails.

Copy link
Contributor Author

@kkuehlz kkuehlz Apr 23, 2019

Choose a reason for hiding this comment

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

Errno::result(res) should convert to an Err if forkpty fails, and ? on line 320 should propagate the error.

Copy link
Member

Choose a reason for hiding this comment

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

Ahh, I didn't see that little ?.

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.

Ok, this looks good. All you need to do is add a CHANGELOG entry and squash.


Ok(ForkptyResult {
master: master,
fork_result: fork_result,
Copy link
Member

Choose a reason for hiding this comment

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

Ahh, I didn't see that little ?.

@kkuehlz
Copy link
Contributor Author

kkuehlz commented Apr 23, 2019

@asomers done

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.

Thanks for your contribution!

bors r+

bors bot added a commit that referenced this pull request Apr 23, 2019
1042: pty: Add forkpty r=asomers a=keur



Co-authored-by: Kevin Kuehler <[email protected]>
@bors
Copy link
Contributor

bors bot commented Apr 23, 2019

Build succeeded

@bors bors bot merged commit 26bd036 into nix-rust:master Apr 23, 2019
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.

2 participants