From dcbc9eec9882ad8df612665847693574bcfe1ca2 Mon Sep 17 00:00:00 2001 From: marius Date: Thu, 25 Feb 2021 17:25:52 -0800 Subject: [PATCH 1/2] always pydecref on the main thread --- src/PyCall.jl | 15 +++++++++++++-- src/pybuffer.jl | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index 615f1171..f6eb27f6 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -76,8 +76,19 @@ mutable struct PyObject o::PyPtr # the actual PyObject* function PyObject(o::PyPtr) po = new(o) - finalizer(pydecref, po) - return po + finalizer(_pydecref_eventually, po) + end +end + +# we can only call pydecref from the main thread. if we happen to hit +# GC from a different thread, add the finalizer back to the finalization +# queue to try again later when we'll eventually be on the main thread. +function _pydecref_eventually(po) + if Threads.threadid()==1 + return pydecref(po) + else + finalizer(_pydecref_eventually, po) + return nothing end end diff --git a/src/pybuffer.jl b/src/pybuffer.jl index a2cec72d..cdabca14 100644 --- a/src/pybuffer.jl +++ b/src/pybuffer.jl @@ -32,7 +32,7 @@ mutable struct PyBuffer b = new(Py_buffer(C_NULL, PyPtr_NULL, 0, 0, 0, 0, C_NULL, C_NULL, C_NULL, C_NULL, C_NULL, C_NULL, C_NULL)) - finalizer(pydecref, b) + finalizer(_pydecref_eventually, b) return b end end From c707032283148216ef90b6b82090025f127d1f38 Mon Sep 17 00:00:00 2001 From: marius Date: Fri, 26 Feb 2021 12:19:00 -0800 Subject: [PATCH 2/2] fix return --- src/PyCall.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index f6eb27f6..51de339b 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -85,11 +85,11 @@ end # queue to try again later when we'll eventually be on the main thread. function _pydecref_eventually(po) if Threads.threadid()==1 - return pydecref(po) + pydecref(po) else finalizer(_pydecref_eventually, po) - return nothing end + return nothing end PyPtr(o::PyObject) = getfield(o, :o)