Tail -f not willing to pipe as expected

I’m stuck on Stage #BR6 (Rust Track).

As others the behaviour of tail’s “-f” flag is giving me trouble.

Here are my logs:

[compile]    Compiling codecrafters-shell v0.1.0 (/app)
[compile]     Finished `release` profile [optimized] target(s) in 0.85s
[compile] Moved ./.codecrafters/run.sh → ./your_program.sh
[compile] Compilation successful.
[tester::#XK3] Running tests for Stage #XK3 (Pipelines - Multi-command pipelines)
[tester::#XK3] [setup] export PATH=/tmp/mango/blueberry/strawberry:$PATH
[tester::#XK3] [setup] echo -e "blueberry\nstrawberry\nmango\nbanana\ngrape" > "/tmp/bee/file-83"
[tester::#XK3] Running ./your_program.sh
[your-program] $ cat /tmp/bee/file-83 | head -n 3 | wc
[your-program]        3       3      27
[tester::#XK3] ✓ Received expected output
[tester::#XK3] [setup] echo -n "mango" > "/tmp/owl/f-79"
[tester::#XK3] [setup] echo -n "blueberry" > "/tmp/owl/f-39"
[tester::#XK3] [setup] echo -n "pineapple" > "/tmp/owl/f-89"
[tester::#XK3] [setup] echo -n "banana" > "/tmp/owl/f-9"
[tester::#XK3] [setup] echo -n "strawberry" > "/tmp/owl/f-36"
[tester::#XK3] [setup] echo -n "apple" > "/tmp/owl/f-98"
[your-program] $ ls /tmp/owl | tail -n 5 | head -n 3 | grep "f-79"
[your-program] f-79
[tester::#XK3] ✓ Received expected output
[your-program] $ 
[tester::#XK3] Test passed.
[tester::#NY9] Running tests for Stage #NY9 (Pipelines - Pipelines with built-ins)
[tester::#NY9] [setup] export PATH=/tmp/banana/orange/mango:$PATH
[tester::#NY9] Running ./your_program.sh
[your-program] $ echo grape-blueberry | wc
[your-program]        1       1      16
[tester::#NY9] ✓ Received expected output
[your-program] $ ls | type exit
[your-program] exit is a shell builtin
[tester::#NY9] ✓ Received expected output
[your-program] $ 
[tester::#NY9] Test passed.
[tester::#BR6] Running tests for Stage #BR6 (Pipelines - Dual-command pipeline)
[tester::#BR6] [setup] export PATH=/tmp/banana/blueberry/pear:$PATH
[tester::#BR6] Running ./your_program.sh
[tester::#BR6] [setup] echo -e "blueberry orange\nbanana mango\nstrawberry grape\npear apple\npineapple raspberry" > "/tmp/owl/file-76"
[your-program] $ cat /tmp/owl/file-76 | wc
[your-program]        5      10      78
[tester::#BR6] ✓ Received expected response
[tester::#BR6] [setup] echo -e "1. raspberry mango\n2. grape pear\n3. blueberry orange" > "/tmp/bee/file-85"
[your-program] $ tail -f /tmp/bee/file-85 | head -n 5
[tester::#BR6] Didn't find expected line.
[tester::#BR6] Expected: "1. raspberry mango"
[tester::#BR6] Received: "" (no line received)
[tester::#BR6] Assertion failed.
[tester::#BR6] Test failedAnd here’s a snippet of my code:

My code can be found at codecrafters-shell-rust/src/interpret.rs at main · why-not-try-calmer/codecrafters-shell-rust · GitHub (the culprit is the “execute_pipeline” function.

The first command (tail -f …) doesn’t get the chance to write to stdout, but I am not sure as to why. Any help very much appreciated!

I think the problem is that you are waiting till the pipeline finishes, gather output then write to stdout.

The expected behavior is that output is written to stdout as soon as it is processed. You can confirm this by running the example with your system’s shell and observe that each line is printed as soon as you append a new line to the target file.

A solution is to use Stdio::inherit() instead of Stdio::piped() for the final stdout, but you cannot capture output with this approach anymore.

2 Likes

There is also this note for wait_with_output:

The stdin handle to the child process, if any, will be closed before waiting. This helps avoid deadlock: it ensures that the child does not block waiting for input from the parent, while the parent waits for the child to exit.

That could at least be one explanation. The last process stdin is closed immediately before it even gets data.

2 Likes