FIFO에 쓸 때 SIGPIPE 잡기

FIFO에 쓸 때 SIGPIPE 잡기

문제를 재현하는 단계는 다음과 같습니다.

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,

SIGPIPE 신호는 다른 쪽 끝에서 읽기 위해 열려 있지 않은 FIFO에 쓰려고 할 때 프로세스로 전송됩니다.

내가 입력했을 때 DEFFIFO에는 판독기가 남아 있지 않았습니다. 그래서 입력 후 SIGPIPE의 트랩이 트리거되어 DEF적절한 NoReader! 메시지를 표시할 것으로 예상했습니다. 대신 프로세스가 자동으로 종료됩니다. 오류 코드는141, 이는 실제로 SIGPIPE에 의해 종료되었음을 나타냅니다..

반면에 이것을 실행하면newWriter

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

head -c 1 fifo실제로 제1터미널과 제2터미널에서 트랩이 발동됩니다! 그러나 urandom에서 100000바이트가 아닌 1000바이트만 추출하면 트랩이 트리거되지 않습니다.

내가 무엇을 놓치고 있나요? 첫 번째 예에서는 트랩이 트리거되지 않았지만 1000바이트가 아닌 100000바이트 writer에서 트리거되는 이유는 무엇입니까?newWriter

답변1

고양이

트랩 핸들러가 실행되지 않는 이유 는 단순히 신호가 수신되지 않았기 bash때문입니다 . bash쓰기 프로세스에만 전송됩니다 cat.

쉘 자체가 쓰기 작업을 수행하는 경우 트랩 핸들러가 실행됩니다.

#!/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 4096but을 사용해도 오류가 발생하지 않아야 합니다 4097.

관련 정보