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

sleep() before interactive() causes freeze #19

Open
GaryBoone opened this issue Oct 14, 2021 · 15 comments
Open

sleep() before interactive() causes freeze #19

GaryBoone opened this issue Oct 14, 2021 · 15 comments
Labels
help wanted Extra attention is needed

Comments

@GaryBoone
Copy link

The code below run as expected, printing the git diff help, then result StillAlive, then exiting.

fn main() {
    let mut cmd = std::process::Command::new("git");
    cmd.args(["diff"]);
    cmd.current_dir("/tmp");
    let mut session = expectrl::Session::spawn(cmd).expect("Can't spawn a session");
    let mut opts = expectrl::interact::InteractOptions::terminal().unwrap();
    let res = opts.interact(&mut session).unwrap();
    println!("result {:?}", res);
}

This code freezes, printing nothing and not exiting:

fn main() {
    let mut cmd = std::process::Command::new("git");
    cmd.args(["diff"]);
    cmd.current_dir("/tmp");
    let mut session = expectrl::Session::spawn(cmd).expect("Can't spawn a session");
    std::thread::sleep(std::time::Duration::from_millis(300));
    let mut opts = expectrl::interact::InteractOptions::terminal().unwrap();
    let res = opts.interact(&mut session).unwrap();
    println!("result {:?}", res);
}

Hitting return causes the program to continue as before. It seems like the delay is causing expectrl to enter the interactive mode in a blocking way, but that's not quite right because interactive mode should require ^] to exit, not just a return. Also, there's no input command here awaiting a return.

The expected behavior would be that the output is exactly as before but delayed 300ms.

@zhiburt
Copy link
Owner

zhiburt commented Oct 14, 2021

Interesting from a first glance,
Aaaaaaa, but I can imagine what causes this.
Give me a second

The expected behavior would be that the output is exactly as before but delayed 300ms.

Agree, but ...

@zhiburt
Copy link
Owner

zhiburt commented Oct 14, 2021

Do you repeatedly get such a result?

Because I am getting the output without any blocking.
(It is not complete, I probably must add a flow which (may) fix this (ref #18))

[mzhiburt@fedora expectrl]$ cargo run --package expectrl --example expect_line
   Compiling expectrl v0.2.0 (/home/mzhiburt/projects/expectrl)
    Finished dev [unoptimized + debuginfo] target(s) in 1.58s
     Running `target/debug/examples/expect_line`
warning: Not a git repository. Use --no-index to compare two paths outside a working tree
usage: git diff --no-index [<options>] <path> <path>

Diff output format options
    -p, --patch           generate patch
    -s, --no-patch        suppress diff output
    -u                    generate patch
    -U, --unified[=<n>]   generate diffs with <n> lines context
    -W, --function-context
                          generate diffs with <n> lines context
    --raw                 generate the diff in result Exited(Pid(81604), 129)

@zhiburt
Copy link
Owner

zhiburt commented Oct 14, 2021

Are you on macos or linux?
Because as I've seen a couple of times on CI strange behaviour on macos which might be related to this issue.

expectrl/tests/io.rs

Lines 384 to 399 in 3573e41

// #[cfg(not(target_os = "macos"))]
fn try_read_after_process_exit() {
let mut command = Command::new("echo");
command.arg("hello cat");
let mut proc = Session::spawn(command).unwrap();
assert_eq!(proc.wait().unwrap(), WaitStatus::Exited(proc.pid(), 0));
assert_eq!(_p_try_read(&mut proc, &mut [0; 128]).unwrap(), 11);
assert_eq!(_p_try_read(&mut proc, &mut [0; 128]).unwrap(), 0);
assert_eq!(_p_try_read(&mut proc, &mut [0; 128]).unwrap(), 0);
assert!(_p_is_empty(&mut proc).unwrap());
// // on macos we may not able to read after process is dead.
// // I assume that kernel consumes proceses resorces without any code check of parent,
// // which what is happening on linux.

@GaryBoone
Copy link
Author

Yes, the above results were on macos. They occurred repeatedly.

@zhiburt
Copy link
Owner

zhiburt commented Oct 14, 2021

Could you clone the repository and run cargo test?
I am assuming that try_read_after_process_exit will fail

@GaryBoone
Copy link
Author

Will do...

@GaryBoone
Copy link
Author

$  git clone https://github.com/zhiburt/expectrl.git && cd expectrl && cargo test
...
running 15 tests
test check_macros::tests::test_check ... ignored
test expect::tests::test_n_bytes ... ok
test expect::tests::test_eof ... ok
test expect::tests::test_bytes ... ok
test expect::tests::test_bytes_ref ... ok
test expect::tests::test_byte ... ok
test tests::session_as_writer ... ignored
test expect::tests::test_str ... ok
test expect::tests::test_any ... ok
test interact::tests::contains_in_bytes_test ... ok
test expect::tests::test_char ... ok
test session::tests::test_iterator_on_found ... ok
test tests::test_spawn_no_command ... ok
test tests::test_tokenize_command ... ok
test expect::tests::test_regex ... ok

test result: ok. 13 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 0.04s

    Running tests/check.rs (target/debug/deps/check-523dee5bbc96a0c4)

running 10 tests
test check_eof_timeout ... ok
test check_str ... ok
test check_macro_eof ... FAILED
test check_eof ... FAILED
test read_after_check_str ... ok
test check_n_bytes ... ok
test check_macro ... ok
test check_regex ... ok
test check_macro_with_different_needles ... ok
test check_macro_doest_consume_missmatch ... ok

failures:

---- check_macro_eof stdout ----
thread 'check_macro_eof' panicked at 'Unexpected result', tests/check.rs:253:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- check_eof stdout ----
thread 'check_eof' panicked at 'index out of bounds: the len is 0 but the index is 0', src/session.rs:743:18


failures:
    check_eof
    check_macro_eof

test result: FAILED. 8 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.31s

error: test failed, to rerun pass '--test check'
$

@zhiburt
Copy link
Owner

zhiburt commented Oct 15, 2021

Could you run cargo test --no-fail-fast because some tests were not started because of a single fail.

@GaryBoone
Copy link
Author

...
    Running tests/interact.rs (target/debug/deps/interact-c83b4b52c6cdfa0c)

running 7 tests
test interact_callback ... ignored
test interact_on_output_not_matched ... ok
test interact_context ... ok
test interact_callbacks_with_stream_redirection ... ok
test interact_filters ... ok
test interact_stream_redirection ... ok
test interact_callbacks_called_after_exit has been running for over 60 seconds

It froze here. I waited for more than 5 minutes, but it didn't continue.

@zhiburt
Copy link
Owner

zhiburt commented Oct 15, 2021

I see
Could you run try_read_after_process_exit this test has much smaller scope to investigate.
I would expect it will timeouts as well.

cargo test -- try_read_after_process_exit

@GaryBoone
Copy link
Author

Froze! Waited more than 5m.

    Running tests/io.rs (target/debug/deps/io-c034048bff565ae5)

running 1 test
test try_read_after_process_exit has been running for over 60 seconds
^C

@zhiburt
Copy link
Owner

zhiburt commented Oct 15, 2021

Thank you
I'll try to work on this tomorrow if you don't mind.

@zhiburt
Copy link
Owner

zhiburt commented Oct 18, 2021

Just for an update.

Haven't yet cracked this issue.
But I spotted it I hope.

It seems like on macos process always is_alive.
And it can't even be stopped.

@zhiburt
Copy link
Owner

zhiburt commented Oct 28, 2021

Once again just for an update,
I haven't found a solution for this "bug" yet.

But it is 100% related to a core pty lib.

Only found a similar issue in a creack/pty#101
which seems to be unresolved fully.

@zhiburt zhiburt added the help wanted Extra attention is needed label Oct 28, 2021
@zhiburt
Copy link
Owner

zhiburt commented Dec 3, 2021

So it was a while :)

But I guess I figure something out 😄

The issue was not why it doesn't work on freebsd and macos.
But why it works on linux 😃

Have no clue yet why.

But essentially when process is exists.
We can't no longer read anything.
On all platforms.

on linux we get a error in such case but on macos and freebsd we get nothing just an empty stream of data.

I would say we can't do anyting with this at least I don't yet see.

I'll update the doc of interact function accordingly.

But overall that's it.

No surprises 😞

PS: My comment about not stopped macos processes though is interesting. It may need an investigation cause I don't remember what it was 🥲

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants