coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Does head util cause SIGPIPE?


From: Ray Satiro
Subject: Re: Does head util cause SIGPIPE?
Date: Fri, 1 Nov 2019 23:31:31 -0400
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.2.1

On 10/25/2019 6:37 PM, Assaf Gordon wrote:
On 2019-10-25 1:56 a.m., Ray Satiro wrote:
Recently I tracked down a delay in some scripts to this line:

find / -name filename* 2>/dev/null | head -n 1
[...]
owner@ubuntu1604-x64-vm:~$ ( trap '' pipe; find / -name initrd* 2>/dev/null | strace -e 'trace=!all' head -n 1)
/initrd.img
+++ exited with 0 +++
(few seconds wait)

In your case,
I can guess that there is only a single file matching your predicate 'initrd*'.
The 'head' indeed terminates, and the pipe is closed.
But if 'find' doesn't find any more matching files, it doesn't
try to print anything more, and SIGPIPE is never raised.

Note the manual page of pipe(7) says:
?????? "If all file descriptors referring to?? the?? read
???????? end?? of a pipe have been closed, then a write(2)
???????? will cause a SIGPIPE signal to be generated for the
???????? calling process."

So if no further files were found, 'find' continues (slowly scanning
the disk) until it finishes.

Thanks for all the help guys. The explanation quoted above is indeed what is happening: find is only killed by SIGPIPE after it writes again, which in this case it does after it finds the second result.

I probably caused some confusion with my example because I made a mistake. For the purposes of the example I was trying to demonstrate I had reset the sigpipe trap, but actually I ignored it (oops). I wrote trap '' pipe which *ignores* sigpipe (in other words find will keep running after SIGPIPE), but I meant trap - pipe to reset it. Sorry.

I can confirm:

First window:
( trap - pipe; find / -name initrd* 2>/dev/null | head -n 1)

And in second window:
sudo strace -ff -e trace=write?? -e write=1 -p `pgrep find`

Then:

write(1, "/usr/src/linux-headers-4.4.0-34/"..., 127) = -1 EPIPE (Broken pipe) --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=7252, si_uid=1000} ---
+++ killed by SIGPIPE +++

So that's what's happened, killed by SIGPIPE but only after the next write. To remedy I am using the find ... -print -quit instead of head -n 1 to get just the first result , and I will use Stephane's script if I need to get the first n results.

* Note I am not subscribed to the list, I can't get mail from the list for some reason (probably yahoo), so if a reply is necessary I will need a CC to see it.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]