Signals

在寫入 FIFO 時擷取 SIGPIPE

  • July 28, 2020

這些是重現問題的步驟。

writer:

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

打開兩個終端。我將用下面的>T1<>T2<標題來表示它們,用 . 來表示它們的提示$

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

man fifo,

當一個程序嘗試寫入另一端未打開以供讀取的 FIFO 時,會向該程序發送一個 SIGPIPE 信號。

在我進入的時候DEF,FIFO 已經沒有讀卡器了。所以我希望在進入後觸發SIGPIPE上的陷阱DEF以及相應的NoReader! 消息。相反,該過程會靜默終止。錯誤程式碼是141,這表明它確實被 SIGPIPE 終止

另一方面,執行這個**newWriter**

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

在 1 號航站樓和2 號head -c 1 fifo航站樓確實觸發了陷阱!但是,如果我只是從 urandom 中提取 1000 個字節而不是 100000 個字節,則不會觸發陷阱。

我錯過了什麼?為什麼在第一個writer範例中沒有觸發陷阱,而是在newWriter100000 字節(而不是 1000 字節)中?

不執行陷阱處理程序的原因bash僅僅是bash沒有接收到該信號。它僅被發送到寫入過程,即cat.

如果執行寫入的是 shell 本身,則執行陷阱處理程序:

#!/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

strace顯示了head呼叫不同行為的原因:FIFO 緩衝 4096 字節(在我的系統上;可以從核心中檢索到這個值)。所以你不應該得到一個錯誤-c 4096但是4097

引用自:https://unix.stackexchange.com/questions/600715