|
1 | 1 | /* Wrap void * pointers to be passed between C modules */
|
2 | 2 |
|
3 | 3 | #include "Python.h"
|
| 4 | +#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() |
| 5 | +#include "pycore_object.h" // _PyObject_GC_TRACK() |
| 6 | + |
4 | 7 |
|
5 | 8 | /* Internal structure of PyCapsule */
|
6 | 9 | typedef struct {
|
@@ -71,7 +74,7 @@ PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
|
71 | 74 | capsule->destructor = destructor;
|
72 | 75 | capsule->traverse_func = NULL;
|
73 | 76 | capsule->clear_func = NULL;
|
74 |
| - // Only track the capsule if _PyCapsule_SetTraverse() is called |
| 77 | + // Only track the object by the GC when _PyCapsule_SetTraverse() is called |
75 | 78 |
|
76 | 79 | return (PyObject *)capsule;
|
77 | 80 | }
|
@@ -204,8 +207,14 @@ _PyCapsule_SetTraverse(PyObject *op, traverseproc traverse_func, inquiry clear_f
|
204 | 207 | }
|
205 | 208 | PyCapsule *capsule = (PyCapsule *)op;
|
206 | 209 |
|
207 |
| - if (!PyObject_GC_IsTracked(op)) { |
208 |
| - PyObject_GC_Track(op); |
| 210 | + if (traverse_func == NULL || clear_func == NULL) { |
| 211 | + PyErr_SetString(PyExc_ValueError, |
| 212 | + "_PyCapsule_SetTraverse() called with NULL callback"); |
| 213 | + return -1; |
| 214 | + } |
| 215 | + |
| 216 | + if (!_PyObject_GC_IS_TRACKED(op)) { |
| 217 | + _PyObject_GC_TRACK(op); |
209 | 218 | }
|
210 | 219 |
|
211 | 220 | capsule->traverse_func = traverse_func;
|
@@ -306,24 +315,22 @@ capsule_repr(PyObject *o)
|
306 | 315 | static int
|
307 | 316 | capsule_traverse(PyCapsule *capsule, visitproc visit, void *arg)
|
308 | 317 | {
|
309 |
| - if (capsule->traverse_func) { |
310 |
| - return capsule->traverse_func((PyObject*)capsule, visit, arg); |
311 |
| - } |
312 |
| - else { |
313 |
| - return 0; |
314 |
| - } |
| 318 | + // Capsule object is only tracked by the GC |
| 319 | + // if _PyCapsule_SetTraverse() is called |
| 320 | + assert(capsule->traverse_func != NULL); |
| 321 | + |
| 322 | + return capsule->traverse_func((PyObject*)capsule, visit, arg); |
315 | 323 | }
|
316 | 324 |
|
317 | 325 |
|
318 | 326 | static int
|
319 | 327 | capsule_clear(PyCapsule *capsule)
|
320 | 328 | {
|
321 |
| - if (capsule->clear_func) { |
322 |
| - return capsule->clear_func((PyObject*)capsule); |
323 |
| - } |
324 |
| - else { |
325 |
| - return 0; |
326 |
| - } |
| 329 | + // Capsule object is only tracked by the GC |
| 330 | + // if _PyCapsule_SetTraverse() is called |
| 331 | + assert(capsule->clear_func != NULL); |
| 332 | + |
| 333 | + return capsule->clear_func((PyObject*)capsule); |
327 | 334 | }
|
328 | 335 |
|
329 | 336 |
|
|
0 commit comments