Re: file offset corruption on 32-bit machines?

From: Lennart Sorensen
Date: Fri Apr 11 2008 - 13:15:47 EST


On Fri, Apr 11, 2008 at 09:59:45AM -0700, Bryan Henderson wrote:
> >So if you write multithreaded code and don't understand what locking
> >around shared resources is for, then your application might break.
>
> I think I know what locking around shared resources is for, which is why
> I'm surprised the kernel doesn't do it.
>
> Is it normal for a kernel resource not to be thread-safe (i.e. you don't
> get advertised/sensible results if two threads access it at the same
> time)?

If two threads are changing one filehandle at the same time, then the
program is broken. I can't see how the kernel making updates to 64bit
filehandles "atomic" helps. You could still seek in one thread, then
seek in another and then start the write in the first and get a wrong
result. Changes to a shared filehandle of any kind requires locking to
work reliably, so additional slow downs and locking in the kernel won't
fix anything.

> I could accept (though I haven't thought about it) that there aren't any
> real-world applications that do simultaneous reads and writes through the
> same file pointer. I might even accept that there can be no useful
> application that does. But can you say such an application is incorrect?

Unless the application has it's own locking to ensure multiple threads
don't screw up each other's fileposition, it simply wouldn't work.

What is the difference between doing:

threadA: seek(positionA)
threadB: seel(positionB)
threadA: write
threadB: write

versus

threadA: seek(posisionA) but only set half the 64bits
threadB: seek(positionB) set all 64bits
threadA: complete seek operation setting the other half of the bits
threadA: write
threadB: write

either way you end up writing to the wrong file location even though the
first case the kernel made the setting of the fileposition atomic and in
the second case it wasn't.

The application has to do:
threadA: lock access to filehandle
threadA: seek(positionA)
threadB: try to get lock and wait
threadA: write
threadA: unlock
threadB: get lock finally
threadB: seek(positionB)
threadB: write
threadB: unlock

Once the application does locking, it doesn't matter if the setting of
the fileposition is atomic or not since no other thread can touch the
filehandle anyhow.

Doesn't matter if you read or write. If it's a shared filehandle you
have only one current position so to share it you have to lock access
while doing a seek + read or write operation if you want predictable
results.

--
Len Sorensen
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/