diff --git a/NEWS.md b/NEWS.md index 59e0d66d3..e3a53eaf2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # reticulate (development version) +- Fixed segfault encountered when running Python finalizer (#1663, #1664) + # reticulate 1.39.0 - Python background threads can now run in parallel with the R session (#1641). diff --git a/R/package.R b/R/package.R index f8b398b06..a1e4436d4 100644 --- a/R/package.R +++ b/R/package.R @@ -224,7 +224,9 @@ initialize_python <- function(required_module = NULL, use_environment = NULL) { ) - reg.finalizer(.globals, function(e) py_finalize(), onexit = TRUE) + # allow disabling the Python finalizer + if (!tolower(Sys.getenv("RETICULATE_DISABLE_PYTHON_FINALIZER")) %in% c("true", "1", "yes")) + reg.finalizer(.globals, function(e) py_finalize(), onexit = TRUE) # set available flag indicating we have py bindings config$available <- TRUE diff --git a/src/python.cpp b/src/python.cpp index 18c49715c..483a561dc 100644 --- a/src/python.cpp +++ b/src/python.cpp @@ -1167,7 +1167,7 @@ PyObject* pandas_arrays () { } bool is_pandas_na_like(PyObject* x) { - const static PyObjectPtr np_nan(PyObject_GetAttrString(numpy(), "nan")); + const static PyObject* np_nan = PyObject_GetAttrString(numpy(), "nan"); return is_pandas_na(x) || (x == Py_None) || (x == (PyObject*)np_nan); } @@ -1203,11 +1203,16 @@ bool py_is_callable(PyObjectRef x) { // caches np.nditer function so we don't need to obtain it everytime we want to // cast numpy string arrays into R objects. -PyObject* get_np_nditer () { - const static PyObjectPtr np_nditer(PyObject_GetAttrString(numpy(), "nditer")); - if (np_nditer.is_null()) { - throw PythonException(py_fetch_error()); - } +PyObject* get_np_nditer() { + static PyObject* np_nditer = []() -> PyObject* { + PyObject* np_nditer = PyObject_GetAttrString(numpy(), "nditer"); + if (np_nditer == NULL) { + throw PythonException(py_fetch_error()); + } + return np_nditer; + }(); + + // Return the static np_nditer return np_nditer; }