Skip to content

Commit 9c44929

Browse files
committed
Reintroduce workaround for C++ destructors calling Py_DECREF
1 parent 898037a commit 9c44929

File tree

2 files changed

+19
-4
lines changed
  • graalpython
    • com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi
    • com.oracle.graal.python.cext/src

2 files changed

+19
-4
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,22 @@ PyAPI_FUNC(void) initialize_graal_capi(TruffleEnv* env, void* (*getBuiltin)(int
849849
PyTruffle_Log(PY_TRUFFLE_LOG_FINE, "initialize_graal_capi: %fs", ((double) (clock() - t)) / CLOCKS_PER_SEC);
850850
}
851851

852+
/*
853+
This is a workaround for C++ modules, namely PyTorch, that declare global/static variables with destructors that call
854+
_Py_DECREF. The destructors get called by libc during exit during which we cannot make upcalls as that would segfault.
855+
So we rebind them to no-ops when exiting.
856+
*/
857+
Py_ssize_t nop_GraalPy_get_PyObject_ob_refcnt(PyObject* obj) {
858+
return 100; // large dummy refcount
859+
}
860+
void nop_GraalPy_set_PyObject_ob_refcnt(PyObject* obj, Py_ssize_t refcnt) {
861+
// do nothing
862+
}
863+
PyAPI_FUNC(void) finalizeCAPI() {
864+
GraalPy_get_PyObject_ob_refcnt = nop_GraalPy_get_PyObject_ob_refcnt;
865+
GraalPy_set_PyObject_ob_refcnt = nop_GraalPy_set_PyObject_ob_refcnt;
866+
}
867+
852868
static void unimplemented(const char* name) {
853869
printf("Function not implemented in GraalPy: %s\n", name);
854870
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiContext.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ private record ClosureInfo(Object closure, Object delegate, Object executable, l
187187
*/
188188
private final HashMap<Object, ClosureInfo> callableClosureByExecutable = new HashMap<>();
189189
private final HashMap<Long, ClosureInfo> callableClosures = new HashMap<>();
190-
private Object nativeLibrary;
191190

192191
/**
193192
* This list holds a strong reference to all loaded extension libraries to keep the library
@@ -591,11 +590,11 @@ public static CApiContext ensureCapiWasLoaded(Node node, PythonContext context,
591590

592591
@TruffleBoundary
593592
public void finalizeCapi() {
594-
if (nativeLibrary != null) {
593+
if (useNativeBackend && getLLVMLibrary() != null) {
595594
try {
596-
Object initFunction = InteropLibrary.getUncached().readMember(nativeLibrary, "finalizeCAPI");
595+
Object finalizeFunction = InteropLibrary.getUncached().readMember(getLLVMLibrary(), "finalizeCAPI");
597596
Object signature = PythonContext.get(null).getEnv().parseInternal(Source.newBuilder(J_NFI_LANGUAGE, "():VOID", "exec").build()).call();
598-
SignatureLibrary.getUncached().call(signature, initFunction);
597+
SignatureLibrary.getUncached().call(signature, finalizeFunction);
599598
} catch (InteropException e) {
600599
throw CompilerDirectives.shouldNotReachHere(e);
601600
}

0 commit comments

Comments
 (0)