On 25/09/2026 14:47, Taylor R Campbell wrote:
Date: Thu, 24 Sep 2026 07:52:12 -0700
From: Collin Funk <[email protected]>

It has been a while since I looked at pipe-f2.sh, but I remember coming
to the conclusion that it was a NetBSD bug [1]. I never managed to
create a simple reproduction to report, and feel a bit bad just sending
over a long test case and asking them to fix it for me.

I would be curious to see how you came to that conclusion!

I compared ktraces of coreutils tail(1) and NetBSD's tail(1) in a
reduced test case of:

$ rm -f out exp
$ mkfifo out
$ echo 1 >out & echo=$!
$ ktrace tail -f out >exp & tail=$!
$ wait $echo
$ sleep 5
$ kill $tail
$ wait $tail
$ kdump -R | grep -v mmap | tail -20

I inserted a sleep and used kdump -R (show relative timestamps) so you
can see where the time is spent -- you'll see that it is only in the
very last read _after_ the fifo reports EOF.

Here's the output for NetBSD tail(1):

  29985  29985 tail     0.000000764 RET   __fstat50 0
  29985  29985 tail     0.000006412 CALL  read(3,0x730a164d1000,0x1000)
  29985  29985 tail     0.000006292 GIO   fd 3 read 2 bytes
        "1\n"
  29985  29985 tail     0.000000355 RET   read 2
  29985  29985 tail     0.000008934 CALL  read(3,0x730a164d1000,0x1000)
  29985  29985 tail     0.000001248 GIO   fd 3 read 0 bytes
        ""
  29985  29985 tail     0.000000207 RET   read 0
  29985  29985 tail     0.000001842 CALL  write(1,0x730a164c0000,2)
  29985  29985 tail     0.000005768 GIO   fd 1 wrote 2 bytes
        "1\n"
  29985  29985 tail     0.000000270 RET   write 2
  29985  29985 tail     0.000003033 CALL  kqueue
  29985  29985 tail     0.000000944 RET   kqueue 4
  29985  29985 tail     0.000003459 CALL  __kevent50(4,0x7f7fff2787a0,1,0,0,0)
  29985  29985 tail     0.000001950 RET   __kevent50 0
  29985  29985 tail     0.000001287 CALL  read(3,0x730a164d1000,0x1000)
  29985  29985 tail     5.002272721 RET   read RESTART
  29985  29985 tail     0.000001185 PSIG  SIGTERM SIG_DFL: code=SI_USER sent by 
pid=5142, uid=1000)

Here's the output for coreutils tail(1);

  16702  16702 tail     0.000012542 CALL  open(0x7f7fffb6ad6f,0,0)
  16702  16702 tail     0.000000728 NAMI  "out"
  16702  16702 tail     0.000003938 RET   open 3
  16702  16702 tail     0.000002380 CALL  __fstat50(3,0x7f7fffb6a630)
  16702  16702 tail     0.000000792 RET   __fstat50 0
  16702  16702 tail     0.000008315 CALL  read(3,0x73aa41997500,0x400)
  16702  16702 tail     0.000089855 GIO   fd 3 read 2 bytes
        "1\n"
  16702  16702 tail     0.000000594 RET   read 2
  16702  16702 tail     0.000003812 CALL  read(3,0x73aa41997500,0x400)
  16702  16702 tail     0.000018985 GIO   fd 3 read 0 bytes
        ""
  16702  16702 tail     0.000000385 RET   read 0
  16702  16702 tail     0.000017100 CALL  __fstat50(1,0x7f7fffb6a280)
  16702  16702 tail     0.000001326 RET   __fstat50 0
  16702  16702 tail     0.000006237 CALL  __fstat50(1,0x7f7fffb6a590)
  16702  16702 tail     0.000000623 RET   __fstat50 0
  16702  16702 tail     0.000001737 CALL  read(3,0x7f7fffb6a0b0,0x400)
  16702  16702 tail     5.002260818 RET   read RESTART
  16702  16702 tail     0.000001380 PSIG  SIGTERM SIG_DFL: code=SI_USER sent by 
pid=29372, uid=1000)

As you can see, the process wakes up promptly to receive the zero-byte
return from read() indicating EOF in both cases, but the coreutils
tail(1) doesn't write anything after that -- it fstats stdout a couple
times, but then goes right back to reading until SIGTERM is delivered.

So this is not consistent with the hypothesis laid out at
<https://lists.gnu.org/archive/html/coreutils/2026-04/msg00129.html>
that NetBSD fails to indicate EOF promptly.

The point wasn't about the first read(),
it was about the blocking in the subsequent read().

On Linux for example we see read() always returning 0:

  read(3, "x\n", 8192)                    = 2
  read(3, "", 8192)                       = 0

  read(3, "", 8192)                       = 0
  clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0})
  read(3, "", 8192)                       = 0
  clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0})
  ...

Padraig



Reply via email to