1

These are the steps to reproduce the problem.

writer:

#!/bin/bash
trap 'echo NoReader!' PIPE
cat > fifo

Open two terminals. I will denote them by the >T1< and >T2< headers below, and their prompts by $.

>T1<
$ mkfifo fifo
$ bash writer
ABC
>T2<
$ cat fifo
ABC
^C
>T1<
DEF
$ echo $?
141

From man fifo,

When a process tries to write to a FIFO that is not opened for read on the other side, the process is sent a SIGPIPE signal.

At the time I enter DEF, the FIFO has no reader anymore. So I expected the trap on SIGPIPE to be triggered after entering DEF and the corresponding NoReader! message. Instead, the process silently terminates. The error code is 141, which indicates that it was terminated indeed by SIGPIPE.

On the other hand, executing this newWriter

#!/bin/bash
trap 'echo NoReader!' PIPE
var=$(head -c 100000 /dev/urandom)
echo "$var" > fifo

in terminal 1 and head -c 1 fifo in terminal 2 does trigger the trap! However, if I just extract 1000 bytes from urandom instead of 100000, the trap is not triggered.

What am I missing? Why wasn't the trap triggered in the first writer example, but was in the newWriter with 100000 bytes (and not with 1000 bytes)?

Quasímodo
  • 18,865
  • 4
  • 36
  • 73

1 Answers1

2

cat

The reason why the bash trap handler is not executed is simply the fact that bash does not receive that signal. It is sent to the writing process only which is cat.

The trap handler is executed if it is the shell itself which does the write:

#!/bin/bash

exec 3>fifo trap 'echo NoReader!' PIPE while IFS= read -r -d '' -n 1 input; do printf %s "$input" >&3 || break done </dev/urandom

head

strace shows the reason for the different behaviour of the head calls: The FIFO buffers 4096 bytes (on my system; somehow this value can be retrieved from the kernel). So you should not get an error with -c 4096 but with 4097.

Hauke Laging
  • 90,279
  • Thank you for the answer. It may be helpful to add How big is the pipe buffer?. I found that the buffer was 65536 B in size and confirmed what you said. Also may be helpful to add that newWriter's trap was triggered because what was used to write to the FIFO was echo, a shell builtin, so the shell caught the signal. – Quasímodo Jul 28 '20 at 15:56