Reputation: 2664
I am writing a program that takes requests to read files and then send their contents via a TCP socket (an HTTP server). Clients are served simultaneously across multiple threads, and it has come to my attention that it is completely possible two clients will request the same file simultaneously.
My hope is that if Thread 1 calls fopen(path,"rb");
and then Thread 2 also calls fopen(path,"rb"); // Same path.
that, since both of these are opening the file at path
in read mode, that given the path is valid both calls should succeed.
However I do have concern that after Thread 1 opens a FILE*
that Thread 2's call to fopen
will return NULL
due to there already being an open file handle, and in the context of my HTTP server this would cause the client to wrongfully receive a 404 Not Found
error page, instead of the resource requested, which of course is not the desired result.
I'm sure there are ways to synchronize access or share file handles between these threads, but for sake of simplicity I'd like to be able to avoid implementing these more complex mechanisms.
On Windows with MinGW-w64 I find that this code:
#include <stdio.h>
int main ()
{
FILE* handle1 = fopen("testfile.txt","rb");
FILE* handle2 = fopen("testfile.txt","rb");
printf("%llX\n",handle1);
printf("%llX\n",handle2);
char buf [8];
for (int i = 0; i < 8; i++) buf[i] = 'X';
fread(buf,1,8,handle1);
for (int i = 0; i < 8; i++) putchar(buf[i]);
putchar('\n');
for (int i = 0; i < 8; i++) buf[i] = 'X';
fread(buf,1,8,handle2);
for (int i = 0; i < 8; i++) putchar(buf[i]);
putchar('\n');
};
with testfile.txt
containing File Contents
produces the following output:
7FFE2439FA90
7FFE2439FAC0
File Con
File Con
...which is what I want it to do.
However I want to know whether this behavior is standard, or is only behaving as I want due to something about Windows or about the standard library implementation that my code is linking to.
If it is standard (or, at least common enough to be portable between Windows and Linux) behavior, I get to avoid making my code more convoluted than it needs to be. However of course, if it is not portable behavior, then I do need to figure something out.
TL;DR:
If "file.txt" is a valid path, then in the following code:
char* path = "file.txt";
FILE* file1 = fopen(path,"r");
FILE* file2 = fopen(path,"r");
across a variety of platforms,
file2 != file1
be guaranteed?file2 != NULL
be guaranteed?file1
still be valid?Upvotes: 0
Views: 1659
Reputation: 73041
Opening the same file for read-only access from multiple file-handles at once is not a problem; it will work reliably as expected. Since no data in the file is being modified, and since all the transient state-data (e.g. buffered data, current-seek-position) is held in the FILE
structure itself (and each thread has its own separate/private FILE
structure), there is no race condition.
Will file2 != file1 be guaranteed?
Yes.
Will file2 != NULL be guaranteed?
Yes (assuming the file didn't get deleted or renamed between the two calls, of course :))
Will file1 still be valid?
Yes.
Will this have a danger of causing undefined behavior?
No.
Will this have a danger of causing a data race?
No.
Upvotes: 2