fix: don't skip over lines during file rotation #14
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The Problem
I found a bug in file-tail in which it occasionally fails to pick up newly added lines when the target file is rotated.
When file-tail reaches EOF while reading a file, it re-stats the file path to ensure that it's still operating against the same file. If it detects that the original file is no longer there, it reopens the file and resumes reading from the beginning of the file. This way, file-tail can keep tail-ing files that are periodically rotated.
However, depending on the timing of events, file-tail resumes reading from the end of the new file instead of the beginning. If the target file doesn't exist when stat-ing the file but is recreated just before it's reopened, file-tail reads the new file from the end. When this happens, file-tail skips over the existing contents of the new file that are written before it's opened. Here's an example timeline:
file.txt
.file.txt
is moved tofile.txt.bak
.file.txt
and gets anENOENT
resposne.file.txt
is newly created.file.txt
and resumes reading from the end of the file.Reproduction Steps
The problem can be triggered using two separate processes. I'll refer to them as the reader and writer processes.
The writer process counts numbers starting from 0 and appends those numbers line by line to
file.txt
. When the count reaches 99, it rotates the file by renamingfile.txt
tofile.txt.bak
and creating a newfile.txt
. It then repeats the process by counting again from 0.The reader process, on the other hand, uses file-tail to tail
file.txt
. It tracks the numbers written to the file and verifies that it counts up from 0 through 99 in a loop. If it finds a missing number, it will stop running. If the reader process stops running, that means it skipped over some lines during file rotation.Reliable reproduction might be difficult because execution timing is key to triggering the bug.
Here are the code for both the reader and writer processes:
reader:
writer:
The fix
Always make file-tail read the reopened file from the beginning.