Skip to content

tail: fix -f/-F not following files on Windows (#4827)#13248

Open
crutkas wants to merge 1 commit into
uutils:mainfrom
crutkas:fix/tail-follow-windows-4827
Open

tail: fix -f/-F not following files on Windows (#4827)#13248
crutkas wants to merge 1 commit into
uutils:mainfrom
crutkas:fix/tail-follow-windows-4827

Conversation

@crutkas

@crutkas crutkas commented Jul 1, 2026

Copy link
Copy Markdown

Problem

Fixes #4827tail -f / tail -F does not follow a growing file on Windows. tail prints the initial tail, then never emits appended content.

Root cause

The follow event loop in src/uu/tail/src/follow/watch.rs (Observer::handle_event) matched:

  • Modify(Data(DataChange::Any))
  • Modify(Metadata(Any | WriteTime))
  • Modify(Name(RenameMode::To))
  • Create(..)

…but not the bare Modify(ModifyKind::Any).

notify's Windows ReadDirectoryChangesW backend maps every file write (FILE_ACTION_MODIFIED) to exactly EventKind::Modify(ModifyKind::Any) (notify/src/windows.rs). So on Windows every append/truncate event fell through to _ => {} and was silently dropped — the file was watched, events arrived, paths matched, but nothing was ever read/printed.

Linux inotify emits the more specific Modify(Data(..)), which is why the bug is Windows-only. The macOS/BSD kqueue backend also emits Modify(ModifyKind::Any) for NOTE_WRITE, so this fix hardens follow there too. The polling fallback only emits Data/Metadata, so this arm is a no-op for it and for inotify.

Fix

Add ModifyKind::Any to the match arm (one line + explanatory comment). It routes through the existing tailable/truncation logic, so appends and in-place truncation are both handled.

Tests

Re-enabled the seven Windows follow tests that were disabled with // FIXME: test times out / for currently not working platforms — they timed out because of this bug and now pass:

  • Append following: test_follow_single, test_follow_multiple, test_follow_name_multiple, test_n0_with_follow
  • Truncation: test_follow_name_truncate1, test_follow_name_truncate2, test_follow_name_truncate3

These are genuine regression guards (verified on Windows):

  • Without the fix: test_follow_single and test_follow_name_truncate1 FAIL.
  • With the fix: full Windows follow suite is green.

Known limitation (out of scope for this PR)

test_follow_name_truncate4 and the move/rename follow tests remain Windows-disabled for a different reason: MetadataExtTail::file_id_eq() is stubbed to false on Windows in paths.rs (it needs GetFileInformationByHandle / the windows_by_handle API to compare file identity). Truncate-to-same-content and rename detection depend on that, so tail spuriously reports "file has been replaced". That is a separate follow-up.

@codspeed-hq

codspeed-hq Bot commented Jul 1, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 4.62%

❌ 1 regressed benchmark
✅ 330 untouched benchmarks
⏩ 46 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation sort_ascii_utf8_locale 15.4 ms 16.1 ms -4.62%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing crutkas:fix/tail-follow-windows-4827 (120a4e8) with main (d967066)

Open in CodSpeed

Footnotes

  1. 46 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/date/date-locale-hour (fails in this run but passes in the 'main' branch)
Congrats! The gnu test tests/cp/sparse-to-pipe is no longer failing!
Note: The gnu test tests/tail/pipe-f is now being skipped but was previously passing.

`handle_event` matched `Modify(Data(..))` and `Modify(Metadata(..))` but
not the bare `Modify(ModifyKind::Any)` that notify's Windows
`ReadDirectoryChangesW` backend emits for every write
(`FILE_ACTION_MODIFIED`). Every append/truncate event was therefore
dropped and `tail -f` never followed a growing file on Windows. The same
event is emitted by the macOS/BSD `kqueue` backend (`NOTE_WRITE`), so this
also hardens follow there. Linux inotify and the polling fallback emit the
more specific `Modify(Data/Metadata)` variants, so this arm is a no-op for
them.

Re-enable the seven Windows follow tests previously disabled with
"FIXME: test times out"/"currently not working platforms" - they timed out
precisely because of this bug and now pass:
  - test_follow_single, test_follow_multiple, test_follow_name_multiple
  - test_n0_with_follow
  - test_follow_name_truncate1, test_follow_name_truncate2, test_follow_name_truncate3

Verified: without the fix test_follow_single and test_follow_name_truncate1
fail; with the fix the full Windows follow suite is green (18 passed).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@crutkas crutkas force-pushed the fix/tail-follow-windows-4827 branch from c32e4c7 to 120a4e8 Compare July 1, 2026 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tail -f not working on windows

1 participant