b1st

Hello,

I have a class that exposes file seek and file read functionalities. A single instance of this class opens exactly one file and can be used in more than one thread. So my question is can thread B seek and change the read pointer while thread A is reading the same file and therefore cause the read function in thread A to return unintended data I'd been convinced that this scenario is in fact possble but have not seen it in practice when I was expecting it.

FileReader class instance fr opens C:\data.dat
Thread A calls fr.seek(100)
Thread A calls fr.read(1000)
Thread A gets interrupted while reading
Thread B calls fr.seek(1000000)
Thread B gets interrupted after completing seek
Thread A continues fr.read(1000) execution
fr.read(1000) returns garbage or crashes

I think linux (posix) addresses this potential problem by using pread.

Thanks.


Re: Visual C++ General file seek then read thread-safety

Frank Boyne

Answering your question is a little difficult because you haven't told us anything about how your class implements seek and read.

Assuming that you have used fseek and fread from stdio.h, the following sentences from the documentation would seem to address your question...

fseek: "This function locks out other threads during execution and is therefore thread-safe."

http://msdn2.microsoft.com/en-us/library/75yw9bf3(VS.80).aspx

fread: "This function locks out other threads."

http://msdn2.microsoft.com/en-us/library/kt0etdcs(vs.80).aspx





Re: Visual C++ General file seek then read thread-safety

Sdi

That isn't the failure scenario; the failing sequence is

Thread A does fseek()

Interrupt

Thread B does fseek()

Then, no matter whether there's another interrupt before or after B's fread(), A will eventually fread() the wrong data.

The fact that fseek() is internally thread-safe is not any help. Combined Seek+Read or Seek+Write operations have to be made atomic in your code.





Re: Visual C++ General file seek then read thread-safety

Frank Boyne

Good point. I was a bit too literal, answering the specific scenario posed without looking for other potential failures. Thanks for catching that!





Re: Visual C++ General file seek then read thread-safety

b1st

Frank,

I'm using SetFilePointerEx and ReadFile functions. I'm guessing fseek and fread uses these functions underneath so those two calls also block out other threads

Sdi,

You're absolutely correct that another seek can come in between a seek-then-read operation and I'll need a critical section for it.

It sounds like I'll need to create a windows equivalent of pread:

int pread(handle, location, size, data*)
{
enter critical section
seek
read
leave critical section
}


Thanks.




Re: Visual C++ General file seek then read thread-safety

Frank Boyne

b1st wrote:
I'm using SetFilePointerEx and ReadFile functions. I'm guessing fseek and fread uses these functions underneath so those two calls also block out other threads

Probably not. Note this remark in the SetFilePointerEx documentation:

"Use caution when setting the file pointer in a multithreaded application. You must synchronize access to shared resources. For example, an application whose threads share a file handle, update the file pointer, and read from the file must protect this sequence by using a critical section object or a mutex object. For more information about these objects, see Critical Section Objects and Mutex Objects."

http://msdn2.microsoft.com/en-us/library/aa365542.aspx





Re: Visual C++ General file seek then read thread-safety

Sdi

Code Snippet

int pread(handle, location, size, data*)
{

enter critical section
seek
read
leave critical section

}

Exactly. I'd think this is a pretty common pattern; you'd think that Windows would provide it directly, but there would be the issue of who provides and maintains the critical section. Sounds like a job for a CThreadSafeFileReader class.