Odd behaviour about IO with Unix piping

I run into odd behaviour about IO with Unix piping.

It is ok when it grepped without -q option.
However, it cause error when it grepped with -q option.

How to avoid error with using -q option?

/Users/niku% elixir -v
Erlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Elixir 1.3.4
/Users/niku% mix help | grep help
mix help              # Prints help information for tasks
mix hex               # Prints Hex help information
/Users/niku% mix help | grep -q help
** (ErlangError) erlang error: :terminated
    (stdlib) :io.put_chars(#PID<0.48.0>, :unicode, [[[], "mix hex.build         # Builds a new package version locally"], 10])
    (elixir) lib/enum.ex:651: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:651: Enum.each/2
    (mix) lib/mix/tasks/help.ex:50: Mix.Tasks.Help.run/1
    (mix) lib/mix/task.ex:296: Mix.Task.run_task/3
    (mix) lib/mix/cli.ex:58: Mix.CLI.run_task/2
1 Like

It looks like that’s how Mix responds to being SIGPIPEd:

Maybe mix help 2> /dev/null | grep -q help or grep -q help <<< $(mix help) will work?

Edit: I think mix help | grep help > /dev/null is a little nicer than my second example.

1 Like

All of your suggestions work well.

/Users/niku% mix help 2> /dev/null | grep -q help; echo $?
0
/Users/niku% mix help 2> /dev/null | grep -q helpppp; echo $?
1

/Users/niku% grep -q help <<< $(mix help); echo $?
0
/Users/niku% grep -q helpppp <<< $(mix help); echo $?
1

/Users/niku% mix help | grep help > /dev/null; echo $?
0
/Users/niku% mix help | grep helpppp > /dev/null; echo $?
1

Thank you for your quick response :heart:

1 Like

FYI on how Erlang VM handling (or not handling) the SIGPIPE, from http://erlang.org/pipermail/erlang-bugs/2015-May/004948.html :

head -20 will close the pipe after consuming 20 lines from it. Standard Unix
behaviour is to send a SIGPIPE signal to a process that writes to a closed pipe,
and unless caught or ignored that kills the process. It looks like the Erlang
VM ignores SIGPIPE, so the write will instead fail with EPIPE. Presumably
something in the call chain considers that a fatal error and terminates the VM.

Unless there is documentation to the effect that the VM is supposed to handle
this use case, I don’t think this is a bug.

So I think ERTS terminating or crashing when receiving SIGPIPE is not easy to fix.

2 Likes