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?
CodePudding user response:
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.