Repository: numpy/numpy
File: numpy/_core/src/multiarray/multiarraymodule.c (C)

Code before:
        return -1;
    }

    if (PyArray_InitializeCasts() < 0) {
        return -1;
    }

    if (init_string_dtype() < 0) {
        return -1;
    }

    /*
     * Initialize the default PyDataMem_Handler capsule singleton.
     */
    PyDataMem_DefaultHandler = PyCapsule_New(
            &default_handler, MEM_HANDLER_CAPSULE_NAME, NULL);
    if (PyDataMem_DefaultHandler == NULL) {
        return -1;
    }
#ifdef Py_GIL_DISABLED
    int rc = PyUnstable_SetImmortal(PyDataMem_DefaultHandler);
    assert(rc == 1);
    (void)rc;
#endif
    /*
     * Initialize the context-local current handler
     * with the default PyDataMem_Handler capsule.
     */
    current_handler = PyContextVar_New("current_allocator", PyDataMem_DefaultHandler);
    if (current_handler == NULL) {
        return -1;
    }

    if (initumath(m) != 0) {
        return -1;
    }

    if (set_matmul_flags(d) < 0) {
        return -1;
    }

    // initialize static references to ndarray.__array_*__ special methods
    npy_static_pydata.ndarray_array_finalize = PyObject_GetAttrString(
            (PyObject *)&PyArray_Type, "__array_finalize__");
    if (npy_static_pydata.ndarray_array_finalize == NULL) {
        return -1;
    }
    npy_static_pydata.ndarray_array_ufunc = PyObject_GetAttrString(
            (PyObject *)&PyArray_Type, "__array_ufunc__");
    if (npy_static_pydata.ndarray_array_ufunc == NULL) {
        return -1;

Review comment (bug):
Why only do it on the free-threaded build?

Also I slightly prefer registering failure here as a runtime error:

```
diff --git a/numpy/_core/src/multiarray/multiarraymodule.c b/numpy/_core/src/multiarray/multiarraymodule.c
index 2f381a1c7a..2b6e96f952 100644
--- a/numpy/_core/src/multiarray/multiarraymodule.c
+++ b/numpy/_core/src/multiarray/multiarraymodule.c
@@ -5180,6 +5180,12 @@ _multiarray_umath_exec(PyObject *m) {
         return -1;
     }

+    if (PyUnstable_SetImmortal(npy_static_pydata.default_extobj_capsule) == 0) {
+        PyErr_SetString(PyExc_RuntimeError,
+                        "Could not mark memory handler capsule as immortal");
+        return -1;
+    }
+
     if (initumath(m) != 0) {
         return -1;
     }
```

Code after:
        return -1;
    }

    if (PyArray_InitializeCasts() < 0) {
        return -1;
    }

    if (init_string_dtype() < 0) {
        return -1;
    }

    /*
     * Initialize the default PyDataMem_Handler capsule singleton.
     */
    PyDataMem_DefaultHandler = PyCapsule_New(
            &default_handler, MEM_HANDLER_CAPSULE_NAME, NULL);
    if (PyDataMem_DefaultHandler == NULL) {
        return -1;
    }
#ifdef Py_GIL_DISABLED
    if (PyUnstable_SetImmortal(PyDataMem_DefaultHandler) == 0) {
        PyErr_SetString(PyExc_RuntimeError,
                        "Could not mark memory handler capsule as immortal");
        return -1;
    }
#endif
    /*
     * Initialize the context-local current handler
     * with the default PyDataMem_Handler capsule.
     */
    current_handler = PyContextVar_New("current_allocator", PyDataMem_DefaultHandler);
    if (current_handler == NULL) {
        return -1;
    }

    if (initumath(m) != 0) {
        return -1;
    }

    if (set_matmul_flags(d) < 0) {
        return -1;
    }

    // initialize static references to ndarray.__array_*__ special methods
    npy_static_pydata.ndarray_array_finalize = PyObject_GetAttrString(
            (PyObject *)&PyArray_Type, "__array_finalize__");
    if (npy_static_pydata.ndarray_array_finalize == NULL) {
        return -1;
    }
    npy_static_pydata.ndarray_array_ufunc = PyObject_GetAttrString(
            (PyObject *)&PyArray_Type, "__array_ufunc__");