Skip to content

Commit b694ea5

Browse files
committed
Avoid double-free of well-known native wrappers
1 parent 227e689 commit b694ea5

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,8 +1099,8 @@ private static long addNativeRefCount(long pointer, long refCntDelta) {
10991099

11001100
private static long subNativeRefCount(long pointer, long refCntDelta) {
11011101
long refCount = UNSAFE.getLong(pointer + TP_REFCNT_OFFSET);
1102-
assert (refCount & 0xFFFFFFFF00000000L) == 0 : String.format("suspicious refcnt value during managed adjustment for %016x (%d %016x + %d)\n", pointer, refCount, refCount, refCntDelta);
1103-
assert (refCount - refCntDelta) >= 0 : String.format("refcnt below zero during managed adjustment for %016x (%d %016x + %d)\n", pointer, refCount, refCount, refCntDelta);
1102+
assert (refCount & 0xFFFFFFFF00000000L) == 0 : String.format("suspicious refcnt value during managed adjustment for %016x (%d %016x - %d)\n", pointer, refCount, refCount, refCntDelta);
1103+
assert (refCount - refCntDelta) >= 0 : String.format("refcnt below zero during managed adjustment for %016x (%d %016x - %d)\n", pointer, refCount, refCount, refCntDelta);
11041104

11051105
LOGGER.finest(() -> PythonUtils.formatJString("subNativeRefCount %x %x %d + %d", pointer, refCount, refCount, refCntDelta));
11061106

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -438,11 +438,20 @@ public void setContextVarsContext(PContextVarsContext contextVarsContext) {
438438

439439
public void dispose() {
440440
// This method may be called twice on the same object.
441-
if (dict != null && dict.getNativeWrapper() != null) {
442-
PyTruffleObjectFree.releaseNativeWrapperUncached(dict.getNativeWrapper());
441+
442+
/*
443+
* Note: we may only free the native wrappers if they have no PythonObjectReference
444+
* otherwise it could happen that we free them here and again in
445+
* 'CApiTransitions.pollReferenceQueue'.
446+
*/
447+
if (dict != null) {
448+
PythonAbstractObjectNativeWrapper dictNativeWrapper = dict.getNativeWrapper();
449+
if (dictNativeWrapper != null && dictNativeWrapper.ref == null) {
450+
PyTruffleObjectFree.releaseNativeWrapperUncached(dictNativeWrapper);
451+
}
443452
}
444453
dict = null;
445-
if (nativeWrapper != null) {
454+
if (nativeWrapper != null && nativeWrapper.ref == null) {
446455
PyTruffleObjectFree.releaseNativeWrapperUncached(nativeWrapper);
447456
nativeWrapper = null;
448457
}
@@ -2026,7 +2035,12 @@ private void disposeThreadStates() {
20262035
@TruffleBoundary
20272036
private void cleanupCApiResources() {
20282037
for (PythonNativeWrapper singletonNativeWrapper : singletonNativePtrs) {
2029-
if (singletonNativeWrapper != null) {
2038+
/*
2039+
* Note: we may only free the native wrappers if they have no PythonObjectReference
2040+
* otherwise it could happen that we free them here and again in
2041+
* 'CApiTransitions.pollReferenceQueue'.
2042+
*/
2043+
if (singletonNativeWrapper != null && singletonNativeWrapper.ref == null) {
20302044
PyTruffleObjectFree.releaseNativeWrapperUncached(singletonNativeWrapper);
20312045
}
20322046
}

0 commit comments

Comments
 (0)