Version: uutils tail 0.2.2 (Ubuntu 25.10 / questing)
Platform: Linux x86_64
Minimal repro:
tmp=$(mktemp -d)
echo "fileA-line1" > $tmp/A
ln $tmp/A $tmp/now
script -qc "tail -F $tmp/now & sleep 6; kill %1" $tmp/out < /dev/null > /dev/null 2>&1 &
sleep 1
echo "fileB-line1" > $tmp/B
ln $tmp/B $tmp/now.tmp
mv -f $tmp/now.tmp $tmp/now # atomic hard-link replacement
sleep 1
echo "fileB-line2" >> $tmp/B # NOT shown — bug
sleep 3
wait
cat $tmp/out
Actual output:
fileA-line1
tail: '<tmpdir>/now' has been replaced; following new file
fileB-line1
Expected (matches GNU tail 9.5):
fileA-line1
tail: '<tmpdir>/now' has been replaced; following new file
fileB-line1
fileB-line2
So replacement is correctly detected and the new file's initial content is read once, but IN_MODIFY events on the new inode are not handled — appends to the new file after the swap are silently missed.
Same behavior with tail -f (lowercase).
script is just to give tail a PTY so output isn't block-buffered; reproduces identically with a real interactive shell.
Version: uutils tail 0.2.2 (Ubuntu 25.10 / questing)
Platform: Linux x86_64
Minimal repro:
Actual output:
Expected (matches GNU tail 9.5):
So replacement is correctly detected and the new file's initial content is read once, but
IN_MODIFYevents on the new inode are not handled — appends to the new file after the swap are silently missed.Same behavior with
tail -f(lowercase).scriptis just to give tail a PTY so output isn't block-buffered; reproduces identically with a real interactive shell.