I'm writing C code that takes its tasks to do from file (on linux). There are multiple processes in parallel writing to this file (using echo "COMMAND" >> "file_queue_input"
).
Until now this logic is used:
rename (file_queue_input, file_queue_process);
queue_file = fopen (file_queue_process,"r");
while (!feof (queue_file))
{
<process file line by line>
} // end of while reading queue file
fclose (queue_file);
remove (file_queue_process);
Idea was that by moving the file to another name new descriptors will open against the original name and all commands will be read. But reality shows that some commands are lost on the way.
My assumption: the write descriptor is opened before move operation, stays open to the new name, but not yet written its data, file is read without the data and then write descriptor writes the data, but because read loop has already finished there is nobody to read the data and file is deleted. How to prevent this?
What is correct way of reading queue file which is also frequently written to? I'm quite sure I'm not the first person interested in this, but can not find to correct question for google to find something useful.
As requested in comments added minimal example here (please note that I have all the checks, logging etc... but would like to keep the code as short as possible so everything what was not absolutely necessary was deleted): https://drive.google.com/open?id=1U9vh7DEUPopuyTJ5j4J8T8FqVj812AzV
It contain 2 files: Queue_read_test.c
(file which I'm writing and have control of how to do it), bash_load_generator.sh
which is file simulating writers where I have absolutely no control of.
First we check the numbers and run generator, when generator finish we run queue reader:
ice@center:/usr/src/Demo$ ./bash_load_generator.sh
All commands started waiting for finish
DONE
ice@center:/usr/src/Demo$ ./Queue_read_test # Stop with CTRL+C
^CFinished with 10000 queue items read: ice@center:/usr/src/Demo$
Then we run first queue reader and then we run generator in 2nd screen, after all finished and queue file is gone we stop queue reader (this is the real life scenatio):
ice@center:/usr/src/Demo$ ./Queue_read_test # Run in screen 1
ice@center:/usr/src/Demo$ ./bash_load_generator.sh # Run in screen 2
All commands started waiting for finish
DONE
ice@center:/usr/src/Demo$ ls -ltra /tmp/ | grep queue # Check all was processed (no file should be found) in screen 2
ice@center:/usr/src/Demo$
ice@center:/usr/src/Demo$ # return to screen 1 and CTRL+C
^CFinished with 9905 queue items read: ice@center:/usr/src/Demo$
And we see that 95 commands is lost. This is to illustrate the problem described, my question is now maybe thanks to your comments more precise: What can I as author of queue reader do to prevent loss of commands? (without possibility to modify queue writers) Can I check if there are open file descriptors (guess not as I'm not root).