Search code examples
glibcfgetssuse

What happens when the FILE stream file is overwritten


What happens if a file is overwritten between fopen() and fgets()? I have a program that is failing with the following stack trace:

0x00007f9d63629850 (Linux) 
0x00007f9d6253e8ab (/lib64/libc-2.11.3.so) __memchr 
0x00007f9d62523996 (/lib64/libc-2.11.3.so) _IO_getline_info_internal 
0x00007f9d6252d0cd (/lib64/libc-2.11.3.so) __GI_fgets_unlocked 

I have reason to believe the file being read might be being overwritten between fopen() and fgets(). How plausible is this?

We are on SUSE 11.4 with glibc 2.11.3 with all updates and patches applied to glibc.


Solution

  • This depends on how the file is overwritten on disk.

    1. If the file is overwritten in place (same inode), your program will read the new data. fopen does not automatically fill the buffer before the first read, so fgets will fill the buffer and obtain the new data (after a concurrent update).
      • This applies predominantly to local file systems. Most network file systems have optimizations which, in the absence of file locks, may still return the old data.
      • Without file locking, concurrent modification can result in read operations which observe intermediate states.
    2. If the file is replaced (either removed and recreated, or with a rename operation), the old data will be read.