Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the differences between fish shell and bash when handling named pipes?

When executing these command in fish shell

$ mkfifo answer
$ nc -vv -l -k -p 8001 <answer | tee -a answer

The command hangs.
If I write to answer through echo "" > answer. Then the nc resumes and starts listening correctly.
If, in contrary I CTRL-C the hanging process, here is the message:

^C<W> fish: An error occurred while redirecting file 'answer'
open: Interrupted system call

On the other hand, in bash, when executing:

$ mkfifo answer
$ nc -vv -l -k -p 8001 <answer | tee -a answer
Listening on localhost 8001

The command doesn't hang and start listening directly.

What happens differently in fish and in bash that explains this different behavior?

like image 294
Momh Avatar asked Sep 17 '21 01:09

Momh


1 Answers

The key difference is that fish opens redirected files before fork in the parent shell, while bash does it after fork, in the child process.

When you open a named pipe for read, the open call will block until there is a corresponding writer (and vice versa). Your pipeline contains both reader and writer, but requires that the corresponding open calls occur in parallel, in the child processes. In fish nc cannot start until the file is open, so you get a deadlock.

One workaround is to arrange for a child process to open the file on its own, instead of using a redirection. For example this will avoid the deadlock:

cat answer | nc -vv -k -l -p 8001  | tee -a answer

fish behaves this way because it also uses threads, which limits what you can do in a forked child.

like image 77
ridiculous_fish Avatar answered Sep 24 '22 06:09

ridiculous_fish