Skip to content

Commit c633dbb

Browse files
committed
Implement finalizer for PMMap objects
1 parent 1747e28 commit c633dbb

File tree

4 files changed

+98
-33
lines changed

4 files changed

+98
-33
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MMapModuleBuiltins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -240,7 +240,7 @@ PMMap doFile(VirtualFrame frame, Object clazz, int fd, long lengthIn, int flagsI
240240
} catch (PosixException e) {
241241
throw raiseOSErrorFromPosixException(frame, e);
242242
}
243-
return factory().createMMap(clazz, mmapHandle, dupFd, length, access);
243+
return factory().createMMap(getContext(), clazz, mmapHandle, dupFd, length, access);
244244
}
245245

246246
@Specialization(guards = "isIllegal(fd)")

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/MMapBuiltins.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -40,8 +40,6 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.mmap;
4242

43-
import com.oracle.truffle.api.dsl.NeverDefault;
44-
4543
import static com.oracle.graal.python.builtins.objects.mmap.PMMap.ACCESS_COPY;
4644
import static com.oracle.graal.python.builtins.objects.mmap.PMMap.ACCESS_READ;
4745
import static com.oracle.graal.python.nodes.BuiltinNames.J_READLINE;
@@ -71,6 +69,7 @@
7169

7270
import java.util.List;
7371

72+
import com.oracle.graal.python.PythonLanguage;
7473
import com.oracle.graal.python.annotations.ArgumentClinic;
7574
import com.oracle.graal.python.annotations.ArgumentClinic.ClinicConversion;
7675
import com.oracle.graal.python.builtins.Builtin;
@@ -112,21 +111,26 @@
112111
import com.oracle.graal.python.nodes.function.builtins.clinic.LongIndexConverterNode;
113112
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
114113
import com.oracle.graal.python.nodes.util.CastToByteNode;
114+
import com.oracle.graal.python.runtime.AsyncHandler;
115115
import com.oracle.graal.python.runtime.PosixSupportLibrary;
116116
import com.oracle.graal.python.runtime.PosixSupportLibrary.PosixException;
117-
import com.oracle.graal.python.runtime.exception.PythonErrorType;
117+
import com.oracle.graal.python.runtime.PythonContext;
118118
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
119119
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
120120
import com.oracle.graal.python.util.OverflowException;
121121
import com.oracle.graal.python.util.PythonUtils;
122+
import com.oracle.truffle.api.CallTarget;
122123
import com.oracle.truffle.api.CompilerDirectives;
124+
import com.oracle.truffle.api.TruffleLanguage;
123125
import com.oracle.truffle.api.dsl.Cached;
124126
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
127+
import com.oracle.truffle.api.dsl.NeverDefault;
125128
import com.oracle.truffle.api.dsl.NodeFactory;
126129
import com.oracle.truffle.api.dsl.Specialization;
127130
import com.oracle.truffle.api.dsl.TypeSystemReference;
128131
import com.oracle.truffle.api.frame.VirtualFrame;
129132
import com.oracle.truffle.api.library.CachedLibrary;
133+
import com.oracle.truffle.api.nodes.RootNode;
130134
import com.oracle.truffle.api.profiles.BranchProfile;
131135
import com.oracle.truffle.api.profiles.ConditionProfile;
132136
import com.oracle.truffle.api.strings.TruffleString;
@@ -351,11 +355,7 @@ abstract static class CloseNode extends PythonUnaryBuiltinNode {
351355
@Specialization
352356
PNone close(PMMap self,
353357
@CachedLibrary("getPosixSupport()") PosixSupportLibrary posixSupportLib) {
354-
try {
355-
self.close(posixSupportLib, getPosixSupport());
356-
} catch (PosixException e) {
357-
throw raise(PythonErrorType.BufferError, ErrorMessages.CANNOT_CLOSE_EXPORTED_PTRS_EXIST);
358-
}
358+
self.close(posixSupportLib, getPosixSupport());
359359
return PNone.NONE;
360360
}
361361
}
@@ -718,4 +718,39 @@ Object flush(VirtualFrame frame, PMMap self, long offset, Object sizeObj,
718718
return PNone.NONE;
719719
}
720720
}
721+
722+
static class ReleaseCallback implements AsyncHandler.AsyncAction {
723+
724+
private final PMMap.MMapRef ref;
725+
726+
ReleaseCallback(PMMap.MMapRef ref) {
727+
this.ref = ref;
728+
}
729+
730+
@Override
731+
public void execute(PythonContext context) {
732+
if (ref.isReleased()) {
733+
return;
734+
}
735+
PythonLanguage language = context.getLanguage();
736+
CallTarget callTarget = language.createCachedCallTarget(MMapBuiltins.ReleaseCallback.ReleaserRootNode::new, MMapBuiltins.ReleaseCallback.ReleaserRootNode.class);
737+
callTarget.call(ref);
738+
}
739+
740+
private static class ReleaserRootNode extends RootNode {
741+
@Child private PosixSupportLibrary posixSupportLibrary = PosixSupportLibrary.getFactory().createDispatched(1);
742+
743+
ReleaserRootNode(TruffleLanguage<?> language) {
744+
super(language);
745+
}
746+
747+
@Override
748+
public Object execute(VirtualFrame frame) {
749+
PMMap.MMapRef ref = (PMMap.MMapRef) frame.getArguments()[0];
750+
ref.close(posixSupportLibrary, PythonContext.get(this).getPosixSupport());
751+
return null;
752+
}
753+
}
754+
}
755+
721756
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/mmap/PMMap.java

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.oracle.graal.python.builtins.objects.object.PythonObject;
4848
import com.oracle.graal.python.nodes.PConstructAndRaiseNode;
4949
import com.oracle.graal.python.nodes.util.CastToJavaIntExactNode;
50+
import com.oracle.graal.python.runtime.AsyncHandler;
5051
import com.oracle.graal.python.runtime.PosixSupportLibrary;
5152
import com.oracle.graal.python.runtime.PosixSupportLibrary.PosixException;
5253
import com.oracle.graal.python.runtime.PythonContext;
@@ -68,37 +69,27 @@ public final class PMMap extends PythonObject {
6869
public static final int ACCESS_WRITE = 2;
6970
public static final int ACCESS_COPY = 3;
7071

71-
private Object handle;
72+
private final MMapRef ref;
7273
private long pos;
73-
private final int fd; // -1 for anonymous mapping
74-
private final long length;
7574
private final int access;
7675

77-
public PMMap(Object pythonClass, Shape instanceShape, Object handle, int fd, long length, int access) {
76+
public PMMap(Object pythonClass, Shape instanceShape, PythonContext context, Object handle, int fd, long length, int access) {
7877
super(pythonClass, instanceShape);
7978
assert handle != null;
80-
this.handle = handle;
81-
this.length = length;
79+
this.ref = new PMMap.MMapRef(this, handle, context.getSharedFinalizer(), fd, length);
8280
this.access = access;
83-
this.fd = fd;
8481
}
8582

8683
public Object getPosixSupportHandle() {
87-
return handle;
84+
return ref.getReference();
8885
}
8986

90-
void close(PosixSupportLibrary lib, Object posix) throws PosixException {
91-
if (handle != null) {
92-
if (fd != -1) {
93-
lib.close(posix, fd);
94-
}
95-
lib.mmapUnmap(posix, handle, length);
96-
handle = null;
97-
}
87+
void close(PosixSupportLibrary lib, Object posix) {
88+
ref.close(lib, posix);
9889
}
9990

10091
boolean isClosed() {
101-
return handle == null;
92+
return ref.isReleased();
10293
}
10394

10495
@ExportMessage
@@ -115,7 +106,7 @@ public int getAccess() {
115106
}
116107

117108
public long getLength() {
118-
return length;
109+
return ref.length;
119110
}
120111

121112
public long getPos() {
@@ -127,7 +118,7 @@ public void setPos(long pos) {
127118
}
128119

129120
public long getRemaining() {
130-
return pos < length ? length - pos : 0;
121+
return pos < ref.length ? ref.length - pos : 0;
131122
}
132123

133124
@ExportMessage
@@ -139,7 +130,7 @@ boolean isBuffer() {
139130
@ExportMessage
140131
int getBufferLength(
141132
@Exclusive @Cached CastToJavaIntExactNode castToIntNode) {
142-
return castToIntNode.execute(length);
133+
return castToIntNode.execute(ref.length);
143134
}
144135

145136
@ExportMessage
@@ -183,4 +174,43 @@ Object acquire(@SuppressWarnings("unused") int flags) {
183174
boolean hasBuffer() {
184175
return true;
185176
}
177+
178+
static class MMapRef extends AsyncHandler.SharedFinalizer.FinalizableReference {
179+
180+
final int fd;
181+
private final long length;
182+
183+
MMapRef(PMMap referent, Object handle, AsyncHandler.SharedFinalizer finalizer, int fd, long length) {
184+
super(referent, handle, finalizer);
185+
this.fd = fd;
186+
this.length = length;
187+
}
188+
189+
@Override
190+
public AsyncHandler.AsyncAction release() {
191+
return new MMapBuiltins.ReleaseCallback(this);
192+
}
193+
194+
void close(PosixSupportLibrary posixLib, Object posixSupport) {
195+
if (isReleased()) {
196+
return;
197+
}
198+
markReleased();
199+
200+
Object handle = getReference();
201+
if (fd != -1) {
202+
try {
203+
posixLib.close(posixSupport, fd);
204+
} catch (PosixException e) {
205+
// ignored (CPython does not check the return value)
206+
}
207+
}
208+
try {
209+
posixLib.mmapUnmap(posixSupport, handle, length);
210+
} catch (PosixException e) {
211+
// ignored (CPython does not check the return value)
212+
}
213+
}
214+
}
215+
186216
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,8 +1192,8 @@ public final PDirEntry createDirEntry(Object dirEntryData, PosixFileHandle path)
11921192
return trace(new PDirEntry(PythonBuiltinClassType.PDirEntry, PythonBuiltinClassType.PDirEntry.getInstanceShape(getLanguage()), dirEntryData, path));
11931193
}
11941194

1195-
public final PMMap createMMap(Object clazz, Object mmapHandle, int fd, long length, int access) {
1196-
return trace(new PMMap(clazz, getShape(clazz), mmapHandle, fd, length, access));
1195+
public final PMMap createMMap(PythonContext context, Object clazz, Object mmapHandle, int fd, long length, int access) {
1196+
return trace(new PMMap(clazz, getShape(clazz), context, mmapHandle, fd, length, access));
11971197
}
11981198

11991199
public final BZ2Object.BZ2Compressor createBZ2Compressor(Object clazz) {

0 commit comments

Comments
 (0)