sh – I wrote a pseudo yes command, but I don't understand why SIGPIPE works.

Question:

$ cat pseudo-yes.sh
#!/bin/sh

while true; do
  printf "y\n"
done
$ 

I pseudo-yes.sh as above. If you use this, for example, as follows, it will behave like a yes command without any problem.

$ ./pseudo-yes.sh | head -n 1
y
$ 

From this behavior, it can be understood that the SIGPIPE signal generated when executing the printf command should be received and processed by pseudo-yes.sh . (Otherwise, you can't get out of the while statement)

I understand that the SIGPIPE signal should be issued to the process that made the write system call.

question:

  • Why is pseudo-yes.sh able to handle SIGPIPE correctly even though the main process that writes is printf ?

supplement:

  • This behavior was observed on both ubuntu and mac-os-x.

Answer: Answer:

printf is a shell built-in command for both Ubuntu /bin/sh (bash, dash or posh) and Mac OS X /bin/sh (bash).

$ /bin/sh -c 'type printf'
printf is a shell builtin

Also, SIGPIPE 's default signal handler is process termination. So when you execute the code in question, the /bin/sh process receives a SIGPIPE signal and exits.

On Ubuntu, if you execute the following, /bin/sh does not start the external command.
(Don't execute system calls fork (2), clone (2), execve (2)),
You can observe that you are receiving SIGPIPE .

$ strace -f /bin/sh -c 'while true; do printf "y\n"; done' |head -n 1

Therefore, it works as expected.

Assuming that printf is not built-in /bin/sh , let's end it if the exit code of printf is other than 0 as follows. If the printf (1) process exits after receiving SIGPIPE , the exit code will be 128 + an integer value of SIGPIPE (typically 13) = 141.

#!/bin/sh

while true; do
  printf "y\n" || exit $?
done
Scroll to Top