Skip to content

Commit

Permalink
Fix module init for Python 3.12
Browse files Browse the repository at this point in the history
Python 3.12 changed module init slightly (this may actually be a CPython
3.12 bug, it's not 100% clear). Before Python 3.12 the module wouldn't
be available via `PyState_FindModule` until it was fully initialized.
Now the module is immediately available, but in an invalid state
leading to segfaults. The workaround is to manually call
`PyState_AddModule` to ensure the module is always available.

In the long run we should move to using multiphase module init which
should avoid this problem entirely.
  • Loading branch information
jcrist committed Oct 5, 2023
1 parent a9b9018 commit 04e7a15
Showing 1 changed file with 13 additions and 19 deletions.
32 changes: 13 additions & 19 deletions msgspec/_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -6043,16 +6043,11 @@ StructMeta_new_inner(
/* Fill in struct offsets */
if (structmeta_construct_offsets(&info, cls) < 0) goto cleanup;

/* Cache access to __post_init__ (if defined).
* XXX: When StructMeta is defined, the module hasn't finished initializing
* yet so `mod` will be NULL here. */
if (mod != NULL) {
cls->post_init = PyObject_GetAttr((PyObject *)cls, mod->str___post_init__);
/* Cache access to __post_init__ (if defined). */
cls->post_init = PyObject_GetAttr((PyObject *)cls, mod->str___post_init__);
if (cls->post_init == NULL) {
PyErr_Clear();
}
else {
cls->post_init = NULL;
}

cls->nkwonly = info.nkwonly;
cls->n_trailing_defaults = info.n_trailing_defaults;
Expand Down Expand Up @@ -21067,17 +21062,6 @@ PyInit__core(void)
if (PyModule_AddObject(m, "UNSET", UNSET) < 0)
return NULL;

/* Initialize the Struct Type */
st->StructType = PyObject_CallFunction(
(PyObject *)&StructMetaType, "s(O){ssss}", "Struct", &StructMixinType,
"__module__", "msgspec", "__doc__", Struct__doc__
);
if (st->StructType == NULL)
return NULL;
Py_INCREF(st->StructType);
if (PyModule_AddObject(m, "Struct", st->StructType) < 0)
return NULL;

/* Initialize the exceptions. */
st->MsgspecError = PyErr_NewExceptionWithDoc(
"msgspec.MsgspecError",
Expand Down Expand Up @@ -21245,5 +21229,15 @@ PyInit__core(void)
CACHED_STRING(str_int, "int");
CACHED_STRING(str_is_safe, "is_safe");

/* Initialize the Struct Type */
PyState_AddModule(m, &msgspecmodule);
st->StructType = PyObject_CallFunction(
(PyObject *)&StructMetaType, "s(O){ssss}", "Struct", &StructMixinType,
"__module__", "msgspec", "__doc__", Struct__doc__
);
if (st->StructType == NULL) return NULL;
Py_INCREF(st->StructType);
if (PyModule_AddObject(m, "Struct", st->StructType) < 0) return NULL;

return m;
}

0 comments on commit 04e7a15

Please sign in to comment.