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 <sza...@google.com> wrote:
>> On Thu, Feb 13, 2014 at 2:51 PM, Karsten Blees <karsten.bl...@gmail.com> 
>> 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

Damn...you'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:

----8<----
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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to