git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Make the git codebase thread-safe

From
Karsten Blees <karsten.blees@gmail.com>
Date
Feb 14, 2014, 23:10 UTC
Message-ID
<52FEA271.2030405@gmail.com>
In-Reply-To
<CAAErz9j=_FpWLSyUk43pp8A6e7Ej0crT8ghW5-yxBEbGkd6O+A@mail.gmail.com>
Am 14.02.2014 20:16, schrieb Zachary Turner:
Show 11 quoted lines
> 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...
Show 33 quoted lines
>>> 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;
>>> }
>>>
>>
Previous: Zachary TurnerNext: Duy Nguyen
Message 47 of 55 in “Make the git codebase thread-safe”
  1. Stefan ZagerFeb 12, 2014
  2. Robin H. JohnsonFeb 12, 2014
  3. Duy NguyenFeb 12, 2014
  4. Karsten BleesFeb 12, 2014
  5. Mike HommeyFeb 12, 2014
  6. Karsten BleesFeb 13, 2014
  7. Stefan ZagerFeb 12, 2014
  8. Duy NguyenFeb 12, 2014
  9. Stefan ZagerFeb 12, 2014
  10. Matthieu MoyFeb 12, 2014
  11. Stefan ZagerFeb 12, 2014
  12. David KastrupFeb 12, 2014
  13. Stefan ZagerFeb 12, 2014
  14. David KastrupFeb 12, 2014
  15. Mike HommeyFeb 12, 2014
  16. David KastrupFeb 13, 2014
  17. Mike HommeyFeb 13, 2014
  18. Mike HommeyFeb 13, 2014
  19. David KastrupFeb 13, 2014
  20. Junio C HamanoFeb 12, 2014
  21. Stefan ZagerFeb 12, 2014
  22. Junio C HamanoFeb 12, 2014
  23. Erik Faye-LundFeb 12, 2014
  24. Stefan ZagerFeb 12, 2014
  25. Erik Faye-LundFeb 12, 2014
  26. Stefan ZagerFeb 12, 2014
  27. Erik Faye-LundFeb 12, 2014
  28. Karsten BleesFeb 12, 2014
  29. Stefan ZagerFeb 12, 2014
  30. Johannes SixtFeb 13, 2014
  31. David KastrupFeb 13, 2014
  32. Stefan ZagerFeb 13, 2014
  33. Zachary TurnerFeb 13, 2014
  34. Karsten BleesFeb 13, 2014
  35. Stefan ZagerFeb 13, 2014
  36. Zachary TurnerFeb 13, 2014
  37. Karsten BleesFeb 14, 2014
  38. Stefan ZagerFeb 14, 2014
  39. brian m. carlsonFeb 13, 2014
  40. Matheus TavaresApr 2, 2019
  41. Duy NguyenApr 2, 2019
  42. David KastrupApr 2, 2019
  43. Duy NguyenApr 2, 2019
  44. David KastrupApr 2, 2019
  45. Matheus Tavares BernardinoApr 2, 2019
  46. Zachary TurnerFeb 14, 2014
  47. Karsten BleesFeb 14, 2014
  48. Duy NguyenFeb 15, 2014
  49. Stefan ZagerFeb 15, 2014
  50. Duy NguyenFeb 15, 2014
  51. Zachary TurnerFeb 15, 2014
  52. Duy NguyenFeb 15, 2014
  53. Junio C HamanoFeb 18, 2014
  54. Zachary TurnerFeb 18, 2014
  55. Stefan ZagerFeb 14, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.