Am 14.02.2014 20:16, schrieb Zachary Turner:
> For the mixed read, we wouldn't be looking for another caller of
> pread() (since it doesn't care what the file pointer is), but instead
> a caller of read() or lseek() (since those do depend on the current
> file pointer). In index-pack.c, I see two possible culprits:
>
> 1) A call to xread() from inside fill()
> 2) A call to lseek in parse_pack_objects()
>
> Do you think these could be related? If so, maybe that opens up some
> other solutions?
>
Yeah, I think that's it. The problem is that the single-threaded part
(parse_pack_objects/parse_pack_header) _also_ calls pread (via sha1_object ->
get_data_from_pack -> unpack_data). So a pread() that modifies the file
position would naturally be bad in this single-threaded scenario. Incidentally,
that's exactly what the lstat64 in the version below fixes (similar to
git_pread).
> BTW, the version you posted isn't thread safe.
It is true that, in a multi-threaded scenario, my version modifies the file
position in some indeterministic way. However, as you noted above, the file
position is irrelevant to pread(), so that's perfectly thread-safe, as long as
all threads use pread() exclusively.
Using [x]read() in one of the threads would _not_ be thread-safe, but we're not
doing that here. Both fill()/xread() and parse_pack_objects()/lseek() are
unreachable from threaded_second_pass(), and the main thread just waits for the
background threads to complete...
>>> 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html