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

Code before:
    int ret = PyErr_WarnEx(warning, msg, 1);
    if (ret == 0 || !unraisable) {
        return ret;
    }
    PyObject *s = PyUnicode_FromString("array_dealloc");
    PyErr_WriteUnraisable(s);  // OK if s = NULL
    Py_XDECREF(s);
    return 0;
}

/* array object functions */

/*
 * Much of the actual work for dealloc, split off for use in __setstate__
 * via dealloc_all_but_self function defined below.
 * If not unraisable, will return -1 on error, 0 on success.
 * If unraisable, always succeeds.
 */
static int
_dealloc_all_but_self(PyArrayObject *self, npy_bool unraisable)
{
    PyArrayObject_fields *fa = (PyArrayObject_fields *)self;
    int retval;

    if (fa->_buffer_info) {
        if (_buffer_info_free(fa->_buffer_info, (PyObject *)self) < 0) {
            if (!unraisable) {
                return -1;
            }
            PyErr_WriteUnraisable(NULL);
        }
        fa->_buffer_info = NULL;
    }

    if (fa->base) {
        if (PyArray_FLAGS(self) & NPY_ARRAY_WRITEBACKIFCOPY)
        {
            char const * msg = "WRITEBACKIFCOPY detected in array_dealloc. "
                " Required call to PyArray_ResolveWritebackIfCopy or "
                "PyArray_DiscardWritebackIfCopy is missing.";
            if (WARN_IN_DEALLOC(PyExc_RuntimeWarning, msg, unraisable) < 0) {
                return -1;  // Can only happen if !unraisable, so pass on.
            }
            retval = PyArray_ResolveWritebackIfCopy(self);
            if (retval < 0)
            {
                if (!unraisable) {
                    return -1;
                }
                PyErr_Print();
                PyErr_Clear();

Review comment (suggestion):
This should only be done for real `dealloc` (there is a guard against calling it when ref count != 0 in the code).

Code after:
write_and_clear_error_if_unraisable(int status, npy_bool unraisable)
{
    if (status < 0 && unraisable) {
        PyErr_WriteUnraisable(npy_interned_str.array_dealloc);
        return 0;
    }
    return status;
}

/* array object functions */

/*
 * Much of the actual work for dealloc, split off for use in __setstate__
 * via clear_array_attributes function defined below.
 * If not unraisable, will return -1 on error, 0 on success.
 * If unraisable, always succeeds, though may print errors and warnings.
 */
static int
_clear_array_attributes(PyArrayObject *self, npy_bool unraisable)
{
    PyArrayObject_fields *fa = (PyArrayObject_fields *)self;

    if (_buffer_info_free(fa->_buffer_info, (PyObject *)self) < 0) {
        if (write_and_clear_error_if_unraisable(-1, unraisable) < 0) {
            return -1;
        }
    }
    fa->_buffer_info = NULL;

    if (fa->base) {
        if (PyArray_FLAGS(self) & NPY_ARRAY_WRITEBACKIFCOPY)
        {
            char const * msg = "WRITEBACKIFCOPY detected in clearing of array. "
                " Required call to PyArray_ResolveWritebackIfCopy or "
                "PyArray_DiscardWritebackIfCopy is missing.";
            int retval = PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1);
            if (write_and_clear_error_if_unraisable(retval, unraisable) < 0) {
                return -1;
            }
            /*
             * prevent reaching 0 twice and thus recursing into dealloc.
             * Increasing sys.gettotalrefcount, but path should not be taken.
             */
            Py_INCREF(self);
            retval = PyArray_ResolveWritebackIfCopy(self);
            if (write_and_clear_error_if_unraisable(retval, unraisable) < 0) {
                return -1;
            }
        }
        /*
         * If fa->base is non-NULL, it is something