OdbBackend: acquire the GIL in the callbacks, fix write_cb's type argument - #1496
Merged
Merged
Conversation
The callbacks libgit2 calls for an OdbBackend implemented in Python called into Python without holding the GIL. That works when libgit2 is entered from the C extension, which keeps the GIL, but not from cffi, which releases it around every C call: Index.add on a repository with such a backend crashes the interpreter (access violation on Windows). Acquire the GIL with PyGILState_Ensure, like the filter callbacks do. Assisted-by: Claude Fable 5.1
The type was passed to PyObject_CallMethod with the "n" format, which reads a Py_ssize_t, but git_object_t is an int. On 64-bit Windows write_cb received garbage in the upper 32 bits, e.g. 2753074036739 (0x28100000003) instead of 3 for a blob. Assisted-by: Claude Fable 5.1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With an
OdbBackendimplemented in Python,Index.add(path)crashes the interpreter (access violation on Windows, Python 3.13, pygit2 1.20.1), single-threaded.Cause: the odb backend callbacks in
src/odb_backend.ccall into Python without holding the GIL. That works when libgit2 is entered from the C extension, which keeps the GIL, but cffi releases it around every C call, sogit_index_add_bypathreaches the callbacks without it.Fix:
PyGILState_Ensure/PyGILState_Releasein each callback, the same pattern as insrc/filter.c. It is re-entrant, so it is fine when the caller already holds the GIL.Second commit:
write_cbreceived itstypeargument through thenformat (Py_ssize_t) thoughgit_object_tis an int; on 64-bit Windows it got e.g. 2753074036739 instead of 3 for a blob. It is now passed asi.Tests:
test_index_add(run in a subprocess, since the failure is a crash) andtest_write_cb. Both fail before and pass after, on Windows x64 with MSVC, CPython 3.13 and libgit2 1.9.7; the full suite passes with the first commit.Not done here:
src/refdb_backend.chas the same missing GIL. Possibly related: #1004.This PR (analysis, patch, tests and this description) was prepared by Claude Fable 5.1, working for @cboos.
🤖 Generated with Claude Code