When tailing multiple files in C/C++ using inotify, is there a risk of a race condition when you read to the end of the file, then the file is written to before you start to poll?
The relevant piece of code starts like:
while (true) {
struct pollfd pfd = { fd, POLLIN, 0 };
int ret = poll(&pfd, 1, 30000); // timeout 30s
if (ret > 0) {
size_t len = read(fd, buf, sizeof(buf));
for (size_t e = 0; e < len; ) {
inotify_event *ev = reinterpret_cast<inotify_event*>(&buf[e]);
int i = 0;
while (wds[i] != ev->wd) {
++i;
}
if (ev->mask & IN_MODIFY) {
FILE* f = ff[i];
fseek(f, pos[i], SEEK_SET);
while (fgets(line[i]+offsets[i], MAX_LINE_LENGTH, f)) {
Does the poll function only return when the file is modified? So what happens if the following sequence happens:
- poll returns signalling file has been added to
- I read until the end of the file
- then the file gets added to
- then I start to poll
will I be stuck until the file is added to once again? Since the inotify_add_watch function only takes file names, it has no idea where I “left” off?
You must read to the end of file after you create the notification. Otherwise, you have exactly this race condition. When you get a notification, you must re-arm the notification system before you read the file to ensure that you get notified of any change that occurred after you read the file.