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.spawn does not set new controlling tty for child #6552

Closed
headius opened this issue Feb 4, 2021 · 17 comments · Fixed by #7393
Closed

PTY.spawn does not set new controlling tty for child #6552

headius opened this issue Feb 4, 2021 · 17 comments · Fixed by #7393
Assignees
Labels
Milestone

Comments

@headius
Copy link
Member

headius commented Feb 4, 2021

As part of work to get our FFI-based io/console green (ruby/io-console#22) I discovered that our PTY module seems to break the subprocess io/console tests. This appears to be because our current PTY.spawn implementation is unable to properly set the new controlling tty, and as a result the raw IO operations in the child are routed back to the parent process.

This leads to several tests hanging on JRuby, since output they expect to read never arrives.

The PTY implementation originally came from @Freaky and has not had many changes since: #3185

The code in CRuby for this logic performs a number of operations in the child before proceeding to exec, and I assume these are the missing pieces needed to grant the child its own tty: https://github.com/ruby/ruby/blob/3108ad7bf3dcae52054a1c29b86246cdb470000b/ext/pty/pty.c#L102-L165

At this point, I do not know how to fix this, so it is a known bug in our PTY module.

One solution might be to finally start shipping a minimal executable that we can use to fork + exec and do these various operations in the child, as a sort of super-posix_spawn. No plans to work on that currently.

headius added a commit to ruby/io-console that referenced this issue Feb 4, 2021
JRuby's PTY.spawn does not produce a process with its own
controlling terminal, which is necessary for testing these raw
escape sequences. This commit marks those tests as pending.

The functionality tested appears to work at a command line, but
due to this PTY bug in JRuby we cannot test it this way.

See jruby/jruby#6552
nobu pushed a commit to ruby/io-console that referenced this issue Feb 5, 2021
JRuby's PTY.spawn does not produce a process with its own
controlling terminal, which is necessary for testing these raw
escape sequences. This commit marks those tests as pending.

The functionality tested appears to work at a command line, but
due to this PTY bug in JRuby we cannot test it this way.

See jruby/jruby#6552
nobu pushed a commit to nobu/ruby that referenced this issue Feb 5, 2021
JRuby's PTY.spawn does not produce a process with its own
controlling terminal, which is necessary for testing these raw
escape sequences. This commit marks those tests as pending.

The functionality tested appears to work at a command line, but
due to this PTY bug in JRuby we cannot test it this way.

See jruby/jruby#6552

ruby/io-console@a486b72e5e
matzbot pushed a commit to ruby/ruby that referenced this issue Feb 5, 2021
JRuby's PTY.spawn does not produce a process with its own
controlling terminal, which is necessary for testing these raw
escape sequences. This commit marks those tests as pending.

The functionality tested appears to work at a command line, but
due to this PTY bug in JRuby we cannot test it this way.

See jruby/jruby#6552

ruby/io-console@a486b72e5e
ruby/io-console@b5c8e7bfd8
@sionescu
Copy link

On *nix platforms, this could be solved by using a C library of mine, libfixposix, which has an API similar to posix_spawn but with more operations. See lfp_spawnattr_setctty.

That library won't work on Windows, but it seems that Windows now has support for PTYs since 2018, and only on Windows 10.

@headius
Copy link
Member Author

headius commented Mar 3, 2021

@sionescu Thank you for reaching out! Your library does indeed look like an excellent set of enhancements for posix_spawn and I will be looking into how we can make use of it. Simplest way might be for us to package it as a Ruby gem that builds it on install and binds it with FFI. Then any Ruby implementation can take advantage of the enhanced spawn capabilities.

@sionescu
Copy link

I'll try to get a release done soon, then come up with a gem that I'd like you to review since I haven't done Ruby since MRuby 1.8 or so.

@headius
Copy link
Member Author

headius commented Mar 10, 2021

@sionescu Oh that would be awesome! We could build a library around it that works the same on all Ruby impls but provides the missing pieces of posix_spawn. Keep me posted, I want like to help but my skills in building and packaging native libraries is limited.

@sionescu
Copy link

@headius Ok, very good. What's your primary OS ? I develop libfixposix on Linux, and although I'm reasonably confident that the library should work on OSX and the BSDs, it's only lightly tested there.

@headius
Copy link
Member Author

headius commented Mar 11, 2021

@sionescu I develop on OSX, @enebo and @kares are on Linux. As an optional gem I am not worried... folks that really need the enhanced spawn capabilities on JRuby could just install the gem and then get full PTY etc support.

@byteit101
Copy link
Member

@sionescu I've been working on integrating libfixposix with JRuby (current progress at https://github.com/byteit101/lfp-process-builder for the moment) and am wondering if you are interested in adding rlimit and umask options to the lfp_spawnattr_* set ? I'm hoping to be able to support a superset of Process.spawn with this work. The only other thing missing is close_others, but as we are in the JVM, I think we can just close_on_exec them all, and don't require libfixposix's help there?

@headius
Copy link
Member Author

headius commented Oct 5, 2022

close_others requires that we can maintain a list of all file descriptors open as in CRuby, I believe, and given the JVM manages it's own descriptors for most IO it is not really feasible. However, most fd are being opened with CLOEXEC so usually we will not leak too many descriptors to the child process.

Having rlimit and umask would be great 😃

@sionescu
Copy link

@byteit101 Yes, I've opened the bugs for adding those two spawn attributes. As for close_others, that's an OSX extension called POSIX_SPAWN_CLOEXEC_DEFAULT and I've opened a bug about that as well.
@headius You don't need to maintain a list of all file descriptors, you just need to know which ones you want the child process to inherit, and set CLOEXEC on all the rest.

@byteit101
Copy link
Member

@sionescu sweet! After further research I think everything is cloexec by default in all the places we care about, so the OSX extension is cool but not needed by us

@headius
Copy link
Member Author

headius commented Oct 13, 2022

which ones you want the child process to inherit, and set CLOEXEC on all the rest

Does this not mean we'd have to know all file descriptors? [descriptors for the child] ∪ [all the rest] = [all the descriptors]

We do not have a way to get a list of all open descriptors that the JVM has opened (but hopefully they are all CLOEXEC).

@sionescu
Copy link

It means you'd only have to specify the descriptors you want the child to inherit, and the library can mass-CLOEXEC all the rest. Because this can be somewhat slow depending on the method of iterating over descriptors (still we're talking about ~1ms), it should be opt-in, hence the POSIX_SPAWN_CLOEXEC_DEFAULT option that I'd like to implement.

@headius
Copy link
Member Author

headius commented Oct 13, 2022

Aha, now I understand. Thanks!

byteit101 added a commit to byteit101/jruby that referenced this issue Oct 15, 2022
byteit101 added a commit to byteit101/jruby that referenced this issue Oct 15, 2022
@byteit101
Copy link
Member

@sionescu I am hoping to have some initial releases of the ffi gems soon, do you think you will have time to review, merge, and release a new version of libfixposix with my changes soon, or should we have a temporary soft-fork while you do that later? If the latter, I think I'll mark the version as 0.4.9?

@sionescu
Copy link

sionescu commented Nov 3, 2022

@byteit101 I'll merge that functionality and make a release at the end of the week.

@sionescu
Copy link

Release 0.5.0 is now live and passes tests on Ubuntu 22.04, OSX/Xcode14.0 and Freebsd 12.1: https://app.travis-ci.com/github/sionescu/libfixposix/builds/257627545

@byteit101
Copy link
Member

Awesome, I'll get to work publishing the low level gems after I remove the uid/gid references after the change I see you made!

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

Successfully merging a pull request may close this issue.

4 participants