Am 14.02.2014 00:09, schrieb Zachary Turner:
> To elaborate a little bit more, you can verify with a sample program
> that ReadFile with OVERLAPPED does in fact modify the HANDLE's file
> position.  The documentation doesn't actually state one way or
> another.   My original attempt at a patch didn't have the ReOpenFile,
> and we experienced regular read corruption.  We scratched our heads
> over it for a bit, and then hypothesized that someone must be mixing
> read styles, which led to this ReOpenFile workaround, which
> incidentally also solved the corruption problems.  We wrote a similar
> sample program to verify that when using ReOpenHandle, and changing
> the file pointer of the duplicated handle, that the file pointer of
> the original handle is not modified.
> We did not actually try to identify the source of the mixed read
> styles, but it seems like the only possible explanation.
> On Thu, Feb 13, 2014 at 2:53 PM, Stefan Zager <> wrote:
>> On Thu, Feb 13, 2014 at 2:51 PM, Karsten Blees <> 
>> wrote:
>>> Am 13.02.2014 19:38, schrieb Zachary Turner:
>>>> The only reason ReOpenFile is necessary at
>>>> all is because some code somewhere is mixing read-styles against the same
>>>> fd.
>>> I don't understand...ReadFile with OVERLAPPED parameter doesn't modify the 
>>> HANDLE's file position, so you should be able to mix read()/pread() however 
>>> you like (as long as read() is only called from one thread).
>> That is, apparently, a bald-faced lie in the ReadFile API doc.  First
>> implementation didn't use ReOpenFile, and it crashed all over the
>> place.  ReOpenFile fixed it.
>> Stefan're right, multi-threaded git-index-pack works fine, but some tests 
fail badly. Mixed reads would have to be from git_mmap, which is the only other 
caller of pread().

A simple alternative to ReOpenHandle is to reset the file pointer to its 
original position, as in compat/pread.c::git_pread. Thus single-theaded code 
can mix read()/pread() at will, but multi-threaded code has to use pread() 
exclusively (which is usually the case anyway). A main thread using read() and 
background threads using pread() (which is technically allowed by POSIX) will 
fail with this solution.

This version passes the test suite on msysgit:

ssize_t mingw_pread(int fd, void *buf, size_t count, off64_t offset)
        DWORD bytes_read;
        OVERLAPPED overlapped;
        off64_t current;
        memset(&overlapped, 0, sizeof(overlapped));
        overlapped.Offset = (DWORD) offset;
        overlapped.OffsetHigh = (DWORD) (offset >> 32);

        current = lseek64(fd, 0, SEEK_CUR);

        if (!ReadFile((HANDLE)_get_osfhandle(fd), buf, count, &bytes_read, 
&overlapped)) {
                errno = err_win_to_posix(GetLastError());
                return -1;

        lseek64(fd, current, SEEK_SET);

        return (ssize_t) bytes_read;

To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to
More majordomo info at

Reply via email to