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

stdin broken since release 0.2.3 #63

Closed
rudolphfroger opened this issue Jan 13, 2023 · 9 comments
Closed

stdin broken since release 0.2.3 #63

rudolphfroger opened this issue Jan 13, 2023 · 9 comments

Comments

@rudolphfroger
Copy link

rudolphfroger commented Jan 13, 2023

Since 0.2.3 the run function now uses output_impl and output_impl is missing the option to allow stdin to be Stdio::inherit(), which I guess should have been the default behaviour. In practice this breaks interaction with commands being executed by run.

I think https://github.com/matklad/xshell/blob/master/src/lib.rs#L1011-L1014 should account for the case where one wants stdin to be inherited. So possibly output_impl also needs a ignore_stdin argument to switch stdin to Stdio::none(). If you want I can write a piece of code to demonstrate the bug.

@rudolphfroger
Copy link
Author

rudolphfroger commented Jan 13, 2023

I've written a snippet to demonstrate the problem:

fn main() {
    let sh = xshell::Shell::new().unwrap();

    let cmd = xshell::cmd!(sh, "test -t 0");
    let result = cmd.run();
    println!("test if stdin is open and associated with a terminal: {result:?}");

    let cmd = xshell::cmd!(sh, "cat");
    let result = cmd.run();
    println!("{result:?}");
}

xshell 0.2.3, doesn't wait for input and gives:

$ test -t 0
test if stdin is open and associated with a terminal: Err(command exited with non-zero code `test -t 0`: 1)
$ cat
Ok(())

xshell 0.2.2, does wait for input and outputs:

$ test -t 0
test if stdin is open and associated with a terminal: Ok(())
$ cat
^C

As expected I had to C-c to stop cat from reading from stdin.

All functions using output_impl() have this problem (also in 0.2.2) it's just that in 0.2.3 run() also started to use output_impl().

@matklad
Copy link
Owner

matklad commented Jul 11, 2023

Stdin is intentionally not inherited by default. xshell is primarily oriented towards non-interactive usage in scripts or larger programs, and there accidentally inheriting stdin might cause a latent bug.

But adding a method to control this behavior, to enable inheriting of stdin, would be useful!

There's also a bigger issue that our overall semantics with inheriting/dev/nulling standard streams seems alll over the place. Eg, the read would inherit stderr, which also feels error prone....

So, it seems like it might make sense to overhaul the overall streams behavior here, to make it more predicatble and robust. The following would make sense to me:

  • Default behavior is to /dev/null stdin, pipe stdout/stderr, but return an error if those are non-empty.
  • Each stream then has inherit/ignore toggles

The run is thus split into two methids with TBD names:

  • one runs command silently just for side-effects (you use that from the guts of a complex system)
  • one echos the command itself, and inherits its streams (you use that for "scripting", to show the resulting logs to the user (eg, in CI)).

We might actually extend this split to non-run commands like read? If I do

let pkgid = cmd!(sh, "cargo pkgid").read()?;

In my CI, I'd probably would love to both:

  • See

    $ cargo pkgid
    file:///home/matklad/p/xshell#0.2.5
    

    printout

  • get the actual string value

This requires some fancy tee-ing of the stdout.

This large overhaul would require 0.3 of course. Toggling just stding inheritance would be a minor patch though!

@blckngm
Copy link

blckngm commented Jul 11, 2023

Some programs use whether the stdin is a tty to decide whether to turn on color output. I had to stay on 0.2.2 for this.

@rudolphfroger
Copy link
Author

This large overhaul would require 0.3 of course. Toggling just stding inheritance would be a minor patch though!

It would be great if this could be added with a simple method.

@maxcountryman
Copy link

Chiming in to mention this is important for e.g. CLIs like tailwindcss: without TTY, the --watch flag doesn't work at all.

@matklad
Copy link
Owner

matklad commented Mar 28, 2024

pipe stdout/stderr, but return an error if those are non-empty.

I've since learned that checking for empty stderr is a wrong thing to do.

While you do generally expect my-command do-thing to return with zero and have empty stderr, there are annoying edge-cases.

For example, it might turn out that my-command is a tool managed by some version manager, like rustup, and, when you run my-command do-thing, the command itself has empty stderr, but you still get

my-command v6.6.6 not found locally
downloading my-command v6.6.6

stderr printouts from that version manager.

@daprilik
Copy link

daprilik commented Aug 2, 2024

Just hit this as well.

Updated xshell, and now our project-local xtask that invokes apt install to install dependencies no longer works 😅
In the interim, I've pinned our project to xshell 0.2.2.

+1 that there should be a way to opt-in to stdin inheritance

cyqsimon added a commit to cyqsimon/openvpn-cred-management that referenced this issue Nov 7, 2024
poljar added a commit to matrix-org/matrix-rust-sdk that referenced this issue Dec 4, 2024
Since xshell 0.2.3 the behavior of the run() function has changed in a
incompatible manner. Namely the stdin for the run() function no longer
inherits stdin from the shell. This makes it impossible for commands
that are executed by the run() function to accept input from the shell.

We don't use this functionality in many places but the `xtask release
prepare` command is now broken.

Let's just pin xshell to a working version while we wait for this to be
resolved upstream.

Upstream-issue: matklad/xshell#63
poljar added a commit to matrix-org/matrix-rust-sdk that referenced this issue Dec 4, 2024
Since xshell 0.2.3 the behavior of the run() function has changed in a
incompatible manner. Namely the stdin for the run() function no longer
inherits stdin from the shell. This makes it impossible for commands
that are executed by the run() function to accept input from the shell.

We don't use this functionality in many places but the `xtask release
prepare` command is now broken.

Let's just pin xshell to a working version while we wait for this to be
resolved upstream.

Upstream-issue: matklad/xshell#63
@cyqsimon cyqsimon mentioned this issue Dec 17, 2024
3 tasks
@cyqsimon
Copy link

Hi all. I've added an option for this in #98. It's not great, but not terrible either. Since owner mentioned a desire to overhaul in 0.3.0, I figured this is okay.

Can you please try out my patch, see if it works for you? Thanks.

andybalaam pushed a commit to matrix-org/matrix-rust-sdk that referenced this issue Dec 18, 2024
Since xshell 0.2.3 the behavior of the run() function has changed in a
incompatible manner. Namely the stdin for the run() function no longer
inherits stdin from the shell. This makes it impossible for commands
that are executed by the run() function to accept input from the shell.

We don't use this functionality in many places but the `xtask release
prepare` command is now broken.

Let's just pin xshell to a working version while we wait for this to be
resolved upstream.

Upstream-issue: matklad/xshell#63
@matklad
Copy link
Owner

matklad commented Dec 23, 2024

Fixed in 0.3, there's now run_interactive specifically to inherit stdin!

@matklad matklad closed this as completed Dec 23, 2024
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 a pull request may close this issue.

6 participants