rsethc
rsethc

Reputation: 2664

Opening two FILE handles in read mode, on the same file, simultaneously

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,

Upvotes: 0

Views: 1659

Answers (1)

Jeremy Friesner
Jeremy Friesner

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

Related Questions