Skip to content

Commit 1da4759

Browse files
committed
fix: PyCapsule_GetDestructor is allowed to return a nullptr destructor
Previously, this code would error out if the destructor happened to be a nullptr. This is incorrect. nullptrs are allowed for capsule destructors. "It is legal for a capsule to have a NULL destructor. This makes a NULL return code somewhat ambiguous; use PyCapsule_IsValid() or PyErr_Occurred() to disambiguate." See: https://docs.python.org/3/c-api/capsule.html#c.PyCapsule_GetDestructor I noticed this while working on a type caster related to #3858 DLPack happens to allow the destructor not to be defined on a capsule, and I encountered such a case. See: https://github.com/dmlc/dlpack/blob/e2bdd3bee8cb6501558042633fa59144cc8b7f5f/include/dlpack/dlpack.h#L219
1 parent 6cb2147 commit 1da4759

File tree

1 file changed

+6
-6
lines changed

1 file changed

+6
-6
lines changed

include/pybind11/pytypes.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,18 +1829,18 @@ class capsule : public object {
18291829
// guard if destructor called while err indicator is set
18301830
error_scope error_guard;
18311831
auto destructor = reinterpret_cast<void (*)(void *)>(PyCapsule_GetContext(o));
1832-
if (destructor == nullptr) {
1833-
if (PyErr_Occurred()) {
1834-
throw error_already_set();
1835-
}
1836-
pybind11_fail("Unable to get capsule context");
1832+
if (PyErr_Occurred()) {
1833+
throw error_already_set();
18371834
}
18381835
const char *name = get_name_in_error_scope(o);
18391836
void *ptr = PyCapsule_GetPointer(o, name);
18401837
if (ptr == nullptr) {
18411838
throw error_already_set();
18421839
}
1843-
destructor(ptr);
1840+
1841+
if (destructor != nullptr) {
1842+
destructor(ptr);
1843+
}
18441844
});
18451845

18461846
if (!m_ptr || PyCapsule_SetContext(m_ptr, (void *) destructor) != 0) {

0 commit comments

Comments
 (0)