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

Proc::Async STDIN isn't handled correctly for all apps #5985

Open
p6rt opened this issue Jan 5, 2017 · 5 comments
Open

Proc::Async STDIN isn't handled correctly for all apps #5985

p6rt opened this issue Jan 5, 2017 · 5 comments

Comments

@p6rt
Copy link

p6rt commented Jan 5, 2017

Migrated from rt.perl.org#130512 (status was 'open')

Searchable as RT130512$

@p6rt
Copy link
Author

p6rt commented Jan 5, 2017

From david@empireofgames.com

I'm attempting to use Perl6 && Proc​::Async to automate a series of tests
that requires interacting with multiple shell-based applications. This is
on Linux using the latest rakduobrew installation as of
yesterday (2016.12-200-gf9ed730).

For some applications, everything works perfectly, while others do not.

SSH is one example. When using key-based logins everything works
perfectly. If not using key-based logins (as required for a certain piece
of hardware I need to work with), the password prompt is not captured by
Proc​::Async. STDIN is read directly from the user shell, and the prompt
itself is never output from the 'tapped' stdout. Further, SSH will refuse
to get even that far if the "-T" parameter is not given to it.

Screen is another example (I'm trying to use this because
Device​::SerialPort hasn't been ported to Perl6 yet). No matter what I try,
screen always aborts with the error "Must be connected to a terminal."

my $serial_proc = Proc​::Async.new(​:w, :r, "screen", "/dev/ttyUSB0",
"38400");

$serial_proc.stdout.tap(-> $v { say $v; });

my $promise = $serial_proc.start;

await $promise;

# Exits almost immediately, with "Must be connect to a terminal" being the
only thing output.

In this case, I found a temporary workaround using (ironically) ssh, for
which the man page documents the "-t -t" option as specifically resolving
this problem by forcing "pseudo-tty allocation."

my $serial_proc = Proc​::Async.new(​:w, :r, "ssh",
"-t","-t","localhost","screen /dev/ttyUSB0 38400")

Another application I need to use with this is a (JTAG) debug tool. An
older version of the tool works perfectly, while the newer version fails to
recognize any STDIN from the script, though it does at least respond to
signals (ie​: SIGINT).

I can't claim that I fully understand what's going on here, but clearly
this has something to do with Perl6's Proc​::Async interface not supplying a
"psuedo-tty".

@p6rt
Copy link
Author

p6rt commented Jan 17, 2017

From @zoffixznet

Some comments on this ticket​:

https://irclog.perlgeek.de/perl6-dev/2017-01-17#i_13935065
jnthn brokenchicken​: I looked at that and thought "is it really reasonable to expect Perl 6 to do that" too, tbh. But yeah, geekosaur++ will likely know better on it :)
13​:43 timotimo ah, yeah, pty support would be good indeed
13​:47 nine The pty command sounds useful for that. Maybe one should just push that in between Perl 6 and the program it runs?

And https://irclog.perlgeek.de/perl6-dev/2017-01-17#i_13936857
geekosaur re https://rt-archive.perl.org/perl6/Ticket/Displ​ay.html?id=130512#ticket-history they are expecting Proc​::Async to be an Expect implementation, essentially. although it might be nice if it did provide the option to use a pty instead of a pipe (this should not be default as it's higher overhead and ptys are a limited resource compared to pipes)

@p6rt
Copy link
Author

p6rt commented Jan 17, 2017

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Jan 17, 2017

From @geekosaur

On Wed, Jan 4, 2017 at 11​:20 PM, David E. <perl6-bugs-followup@​perl.org>
wrote​:

SSH is one example. When using key-based logins everything works
perfectly. If not using key-based logins (as required for a certain piece
of hardware I need to work with), the password prompt is not captured by
Proc​::Async. STDIN is read directly from the user shell, and the prompt
itself is never output from the 'tapped' stdout. Further, SSH will refuse
to get even that far if the "-T" parameter is not given to it.

Screen is another example (I'm trying to use this because
Device​::SerialPort hasn't been ported to Perl6 yet). No matter what I try,
screen always aborts with the error "Must be connected to a terminal."

Strictly speaking, this is not a bug​: the interface for these kinds of
programs is usually some variant of expect (the original being in Tcl, with
versions for Perl 5, Python, and other languages). ptys are a more limited
and more complex (and *far* less portable, in particular not possible on
Windows) resource than pipes, and general subprocess interfaces usually
aren't suitable; and adding the necessary logic to allow ptys to work
properly complicates the common case considerably.

The portability concern also means that pty support likely does not belong
in Perl 6's core, but should be provided by a POSIX support module.

--
brandon s allbery kf8nh sine nomine associates
allbery.b@​gmail.com ballbery@​sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

@p6rt
Copy link
Author

p6rt commented Jan 21, 2017

From david@empireofgames.com

It sounds like the functionality here would be a low-priority feature
request, that perhaps might belong in a separate module from a technical
perspective.

In either case, the official documentation (
https://docs.perl6.org/type/Proc::Async) needs to be updated to reflect
this limitation.

Providing methods to tap into STDIN and STDOUT of a launched application
combined with the statement of "Proc​::Async allows you to run external
commands asynchronously, capturing standard output and error handles, and
optionally write to its standard input." would reasonably imply to any
developer/user that this library is meant to work for any command. The
subtleties of pipes versus PTYs are not mentioned anywhere in the
documentation, and is a topic that nobody not familiar with the low-level
guts of the terminals is likely to know (myself included).

While it adds a lot of overhead, the "ssh -t -t" approach seems to be the
best workaround until somebody develops a true Expect module for Perl6, or
extends Proc​::Async to support PTYs.

On Tue, Jan 17, 2017 at 3​:41 PM, Brandon Allbery via RT <
perl6-bugs-followup@​perl.org> wrote​:

On Wed, Jan 4, 2017 at 11​:20 PM, David E. <perl6-bugs-followup@​perl.org>
wrote​:

SSH is one example. When using key-based logins everything works
perfectly. If not using key-based logins (as required for a certain
piece
of hardware I need to work with), the password prompt is not captured by
Proc​::Async. STDIN is read directly from the user shell, and the prompt
itself is never output from the 'tapped' stdout. Further, SSH will
refuse
to get even that far if the "-T" parameter is not given to it.

Screen is another example (I'm trying to use this because
Device​::SerialPort hasn't been ported to Perl6 yet). No matter what I
try,
screen always aborts with the error "Must be connected to a terminal."

Strictly speaking, this is not a bug​: the interface for these kinds of
programs is usually some variant of expect (the original being in Tcl, with
versions for Perl 5, Python, and other languages). ptys are a more limited
and more complex (and *far* less portable, in particular not possible on
Windows) resource than pipes, and general subprocess interfaces usually
aren't suitable; and adding the necessary logic to allow ptys to work
properly complicates the common case considerably.

The portability concern also means that pty support likely does not belong
in Perl 6's core, but should be provided by a POSIX support module.

--
brandon s allbery kf8nh sine nomine
associates
allbery.b@​gmail.com
ballbery@​sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad
http://sinenomine.net

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

No branches or pull requests

1 participant