Skip to content

Commit 1abefda

Browse files
authored
Fix a data race in nb_meta_cache initialization. (#1301)
We must not overwrite nb_meta_cache if it was already set. In JAX's use of nanobind we have several module that all share the same definition of nb_internals. We observed the following data race when updating to v2.12.0 under Python 3.14t: * thread t1 imports a nanobind module, which sets nb_meta_cache unconditionally. * thread t2 calls nb_type_check, which reads nb_meta_cache. Even though t1 is overwriting nb_meta_cache with the exact same value it already had, this is still a data race and therefore undefined behavior. However there's an easy fix: just don't set nb_meta_cache the second time if it's already set correctly.
1 parent 7d13bfc commit 1abefda

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

src/nb_internals.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,9 @@ NB_NOINLINE void nb_module_exec(const char *name, PyObject *) {
458458
if (internals) {
459459
init_internals(internals);
460460
init_pyobjects(internals);
461-
nb_meta_cache = internals->nb_meta;
461+
if (nb_meta_cache != internals->nb_meta) {
462+
nb_meta_cache = internals->nb_meta;
463+
}
462464
internals_inc_ref();
463465
return;
464466
}
@@ -486,7 +488,9 @@ NB_NOINLINE void nb_module_exec(const char *name, PyObject *) {
486488

487489
init_internals(internals);
488490
init_pyobjects(internals);
489-
nb_meta_cache = internals->nb_meta;
491+
if (nb_meta_cache != internals->nb_meta) {
492+
nb_meta_cache = internals->nb_meta;
493+
}
490494
internals_inc_ref();
491495

492496
Py_DECREF(capsule);
@@ -510,7 +514,9 @@ NB_NOINLINE void nb_module_exec(const char *name, PyObject *) {
510514

511515
init_internals(p);
512516
init_pyobjects(p);
513-
nb_meta_cache = p->nb_meta;
517+
if (nb_meta_cache != p->nb_meta) {
518+
nb_meta_cache = p->nb_meta;
519+
}
514520

515521
#if defined(NB_FREE_THREADED)
516522
p->nb_static_property_disabled = PyThread_tss_alloc();

0 commit comments

Comments
 (0)