You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Bill Stoddard <bi...@wstoddard.com> on 2001/01/09 23:06:16 UTC

File handle caching

When you cache a file handle on *nix, are file pointers maintained per process
or per thread? I thought they were maintained per process which would mean
that file handle caching is broken on *nix since there could easily be a race
condition between calling apr_seek and sendfile.

On Windows, I open cached files for async i/o which effectively gets rid of
the notion of a file pointer. The TransmitFile call must explicitly set the
'begin sending from here' pointer and an 'amount to send'  field (in the
OVERLAPPED structure).  This is also broken on Windows now (with the addition
of filters) since there is no guarantee that a cached file will be sent with
TransmitFile. This means that all Windows file i/o must be able to work
correctly with a file opened for async i/o.  I don't think it will be terribly
difficult to make changes to APR to do async file i/o under the covers but
give the appearance of either synchronous or non-blocking to the APR
application.

Just thinking out loud before I jump back into Apache... Comments welcome :-)

Bill



Re: File handle caching

Posted by dean gaudet <dg...@arctic.org>.
On Tue, 9 Jan 2001, Bill Stoddard wrote:

> When you cache a file handle on *nix, are file pointers maintained per
> process or per thread? I thought they were maintained per process
> which would mean that file handle caching is broken on *nix since
> there could easily be a race condition between calling apr_seek and
> sendfile.

per process.

actually it's more complex than that.  each process, and its threads,
share an array of "struct file *" (structure name varies by kernel), this
is indexed by fd.

struct file * contains the file seek offset, and a pointer to an inode.

the inode contains the rest of the info about the file.

when you fork() the new process gets a copy of the array of struct file *
...

which means a parent and its fork()ed children share the same seek offsets
into their open fds.

but on the specific problem of sharing an fd/offset amongst multiple
threads, there's pread(2)/pwrite(2) interfaces which allow
threaded/multi-process databases to use the same fd for all accesses.
and at least the linux sendfile(2) supports an offset for this reason
('cause i asked for it).

looking at the apr/network_io/unix/sendrecv.c code it looks like freebsd
and HPUX also have offset support in sendfile(), i'd assume they do the
right thing in-kernel to allow multiple threads to use the same fd.  i
would worry if we ever implement a sendfile for other unixes that we can't
use seek/read, we have to use pread() or otherwise lock the file between
seek/read (perhaps a sendfile lock in the apr_file_t).

-dean