Search code examples
cpython-3.xpython-c-apireference-counting

Is the PyObject* returned by PyModule_Create 'borrowed' or 'acquired'?


The latest Python Doc only says this about PyModule_Create:

The module initialization function may create and return the module object directly. This is referred to as “single-phase initialization”, and uses one of the following two module creation functions:

PyObject* PyModule_Create(PyModuleDef *def)

  • Create a new module object, given the definition in def. This behaves like PyModule_Create2() with module_api_version set to PYTHON_API_VERSION.
  • ...

Before it is returned from in the initialization function, the resulting module object is typically populated using functions like PyModule_AddObject().

Also, PyModule_Create isn't on the list from this question. This would suggest the conventional behavior is being followed, namely the caller is expected to 'acquire' the reference to PyObject* being returned.

But yet from this python3porting blog post, it has the following example:

static PyObject *
moduleinit(void)
{
  MOD_DEF(m, "themodulename",
          "This is the module docstring",
  module_methods)

  if (m == NULL)
      return NULL;

  if (PyModule_AddObject(m, "hookable",
         (PyObject *)&hookabletype) < 0)
      return NULL;                         /* line A */

  return m;
}

Would 'line A' not leak the reference for this code path? What is the proper usage and ownership semantics of PyModule_Create?


Solution

  • That code snippet simply isn't managing reference counts correctly. Aside from the leak you spotted, it also forgets to Py_INCREF(&hookabletype), despite the fact that PyModule_AddObject steals a reference to the value.

    As usual where not otherwise specified, PyModule_Create returns a new reference, not a borrowed reference.