Skip to content

Commit 9f071b5

Browse files
committed
Fix ctypes not keeping callbacks alive
1 parent 4434c2d commit 9f071b5

File tree

4 files changed

+39
-56
lines changed

4 files changed

+39
-56
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CThunkObject.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,6 @@ public CThunkObject(Object cls, Shape instanceShape, int nArgs) {
9999
atypes = new FFIType[nArgs];
100100
}
101101

102-
public void createCallback() {
103-
this.pcl_exec = new CtypeCallback(this);
104-
this.pcl_write = this.pcl_exec;
105-
}
106-
107102
@ExportLibrary(InteropLibrary.class)
108103
protected static class CtypeCallback implements TruffleObject {
109104
private final CThunkObject thunk;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CtypesModuleBuiltins.java

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,9 +1096,7 @@ Object _ctypes_callproc(VirtualFrame frame, NativeFunction pProc, Object[] argar
10961096
@Cached PyTypeStgDictNode pyTypeStgDictNode,
10971097
@Cached CallNode callNode,
10981098
@Cached GetResultNode getResultNode,
1099-
@CachedLibrary(limit = "1") InteropLibrary ilib,
1100-
@Cached TruffleStringBuilder.AppendStringNode appendStringNode,
1101-
@Cached TruffleStringBuilder.ToStringNode toStringNode) {
1099+
@CachedLibrary(limit = "1") InteropLibrary ilib) {
11021100
int argcount = argarray.length;
11031101
if (argcount > CTYPES_MAX_ARGCOUNT) {
11041102
throw raise(ArgError, TOO_MANY_ARGUMENTS_D_MAXIMUM_IS_D, argcount, CTYPES_MAX_ARGCOUNT);
@@ -1151,7 +1149,7 @@ Object _ctypes_callproc(VirtualFrame frame, NativeFunction pProc, Object[] argar
11511149
}
11521150
Object result;
11531151
if (mode == BackendMode.NFI) {
1154-
result = callNativeFunction(pProc, avalues, atypes, rtype, ilib, appendStringNode, toStringNode);
1152+
result = callNativeFunction(pProc, avalues, atypes, rtype, ilib);
11551153
} else {
11561154
result = callManagedFunction(pProc, avalues, ilib);
11571155
if (mode == BackendMode.INTRINSIC) {
@@ -1190,10 +1188,12 @@ protected Object getFunction(NativeFunction pProc, String signature) throws Exce
11901188
* NFI compatible native function calls (temporary replacement)
11911189
*/
11921190
Object callNativeFunction(NativeFunction pProc, Object[] avalues, FFIType[] atypes, FFIType restype,
1193-
InteropLibrary ilib, TruffleStringBuilder.AppendStringNode appendStringNode, TruffleStringBuilder.ToStringNode toStringNode) {
1191+
InteropLibrary ilib) {
11941192
Object function;
1195-
if (pProc.function == null) {
1196-
TruffleString signature = FFIType.buildNFISignature(atypes, restype, appendStringNode, toStringNode);
1193+
if (pProc.function != null && equals(atypes, pProc.atypes) && restype == pProc.rtype) {
1194+
function = pProc.function;
1195+
} else {
1196+
TruffleString signature = FFIType.buildNFISignature(atypes, restype);
11971197
try {
11981198
function = getFunction(pProc, signature.toJavaStringUncached());
11991199
} catch (Exception e) {
@@ -1203,17 +1203,6 @@ Object callNativeFunction(NativeFunction pProc, Object[] avalues, FFIType[] atyp
12031203
pProc.rtype = restype;
12041204
pProc.function = function;
12051205
pProc.signature = signature;
1206-
} else {
1207-
if (equals(atypes, pProc.atypes) && restype == pProc.rtype) {
1208-
function = pProc.function;
1209-
} else {
1210-
TruffleString signature = FFIType.buildNFISignature(atypes, restype, appendStringNode, toStringNode);
1211-
try {
1212-
function = getFunction(pProc, signature.toJavaStringUncached());
1213-
} catch (Exception e) {
1214-
throw raise(RuntimeError, FFI_PREP_CIF_FAILED);
1215-
}
1216-
}
12171206
}
12181207
try {
12191208
return ilib.execute(function, avalues);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/FFIType.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
4747
import static com.oracle.graal.python.util.PythonUtils.tsLiteral;
4848

49+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
4950
import com.oracle.truffle.api.strings.TruffleString;
5051
import com.oracle.truffle.api.strings.TruffleStringBuilder;
5152

@@ -189,10 +190,11 @@ private static TruffleString getNFIReturnType(FFIType type) {
189190
return type.type.getNFIType();
190191
}
191192

192-
protected static TruffleString buildNFISignature(FFIType[] atypes, FFIType restype, boolean isCallback,
193-
TruffleStringBuilder.AppendStringNode appendStringNode, TruffleStringBuilder.ToStringNode toStringNode) {
193+
@TruffleBoundary
194+
static TruffleString buildNFISignature(FFIType[] atypes, FFIType restype, boolean isCallback) {
194195
TruffleStringBuilder sb = TruffleStringBuilder.create(TS_ENCODING);
195196
boolean first = true;
197+
TruffleStringBuilder.AppendStringNode appendStringNode = TruffleStringBuilder.AppendStringNode.getUncached();
196198
appendStringNode.execute(sb, T_LPAREN);
197199
for (FFIType type : atypes) {
198200
if (first) {
@@ -201,21 +203,20 @@ protected static TruffleString buildNFISignature(FFIType[] atypes, FFIType resty
201203
appendStringNode.execute(sb, T_COMMA_SPACE);
202204
}
203205
if (type.isCallback()) {
204-
TruffleString subSignature = buildNFISignature(type.callback.atypes, type.callback.ffi_restype, true,
205-
appendStringNode, toStringNode);
206+
TruffleString subSignature = buildNFISignature(type.callback.atypes, type.callback.ffi_restype, true);
206207
appendStringNode.execute(sb, subSignature);
207208
} else {
208209
appendStringNode.execute(sb, isCallback ? getNFICallback(type) : getNFIType(type));
209210
}
210211
}
211212
appendStringNode.execute(sb, T_LEFT_PAREN_COLON);
212213
appendStringNode.execute(sb, getNFIReturnType(restype));
213-
return toStringNode.execute(sb);
214+
return TruffleStringBuilder.ToStringNode.getUncached().execute(sb);
214215
}
215216

216-
protected static TruffleString buildNFISignature(FFIType[] atypes, FFIType restype,
217-
TruffleStringBuilder.AppendStringNode appendStringNode, TruffleStringBuilder.ToStringNode toStringNode) {
218-
return buildNFISignature(atypes, restype, false, appendStringNode, toStringNode);
217+
@TruffleBoundary
218+
static TruffleString buildNFISignature(FFIType[] atypes, FFIType restype) {
219+
return buildNFISignature(atypes, restype, false);
219220
}
220221

221222
enum FieldSet {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/PyCFuncPtrBuiltins.java

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___CALL__;
7575
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___NEW__;
7676
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___REPR__;
77+
import static com.oracle.graal.python.nodes.StringLiterals.J_NFI_LANGUAGE;
7778
import static com.oracle.graal.python.runtime.exception.PythonErrorType.AttributeError;
7879
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
7980
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
@@ -122,7 +123,9 @@
122123
import com.oracle.graal.python.nodes.object.GetClassNode;
123124
import com.oracle.graal.python.nodes.util.CastToJavaIntExactNode;
124125
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
126+
import com.oracle.graal.python.runtime.PythonContext;
125127
import com.oracle.graal.python.runtime.exception.PException;
128+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
126129
import com.oracle.truffle.api.dsl.Bind;
127130
import com.oracle.truffle.api.dsl.Cached;
128131
import com.oracle.truffle.api.dsl.Cached.Shared;
@@ -133,7 +136,9 @@
133136
import com.oracle.truffle.api.dsl.Specialization;
134137
import com.oracle.truffle.api.frame.VirtualFrame;
135138
import com.oracle.truffle.api.nodes.Node;
139+
import com.oracle.truffle.api.source.Source;
136140
import com.oracle.truffle.api.strings.TruffleString;
141+
import com.oracle.truffle.nfi.api.SignatureLibrary;
137142

138143
@CoreFunctions(extendClasses = PythonBuiltinClassType.PyCFuncPtr)
139144
public class PyCFuncPtrBuiltins extends PythonBuiltins {
@@ -262,46 +267,39 @@ FFIType _ctypes_get_ffi_type(Object obj,
262267
return dict.ffi_type_pointer;
263268
}
264269

270+
@TruffleBoundary
265271
CThunkObject _ctypes_alloc_callback(Object callable, Object[] converters, Object restype, int flags,
266272
PyTypeStgDictNode pyTypeStgDictNode) {
267273
int nArgs = converters.length;
268-
CThunkObject p = CThunkObjectNew(nArgs);
274+
CThunkObject thunk = CThunkObjectNew(nArgs);
269275

270-
p.flags = flags;
276+
thunk.flags = flags;
271277
int i;
272278
for (i = 0; i < nArgs; ++i) {
273279
Object cnv = converters[i];
274-
p.atypes[i] = _ctypes_get_ffi_type(cnv, pyTypeStgDictNode);
280+
thunk.atypes[i] = _ctypes_get_ffi_type(cnv, pyTypeStgDictNode);
275281
}
276282

277-
p.restype = restype;
283+
thunk.restype = restype;
278284
if (restype == null || restype == PNone.NONE) {
279-
p.setfunc = FieldSet.nil;
280-
p.ffi_restype = new FFIType();
285+
thunk.setfunc = FieldSet.nil;
286+
thunk.ffi_restype = new FFIType();
281287
} else {
282288
StgDictObject dict = pyTypeStgDictNode.execute(restype);
283289
if (dict == null || dict.setfunc == FieldSet.nil) {
284290
throw raise(TypeError, INVALID_RESULT_TYPE_FOR_CALLBACK_FUNCTION);
285291
}
286-
p.setfunc = dict.setfunc;
287-
p.ffi_restype = dict.ffi_type_pointer;
288-
}
289-
/*-
290-
p.pcl_write = ffi_closure_alloc(sizeof(ffi_closure), p.pcl_exec);
291-
ffi_abi cc = FFI_DEFAULT_ABI;
292-
int result = ffi_prep_cif(p.cif, cc, nArgs, _ctypes_get_ffi_type(restype, pyTypeStgDictNode), p.atypes);
293-
if (result != FFI_OK) {
294-
throw raise(RuntimeError, FFI_PREP_CIF_FAILED_WITH_D, result);
295-
}
296-
result = ffi_prep_closure_loc(p.pcl_write, p.cif, closure_fcn, p, p.pcl_exec);
297-
if (result != FFI_OK) {
298-
throw raise(RuntimeError, FFI_PREP_CLOSURE_FAILED_WITH_D, result);
299-
}
300-
*/
301-
p.createCallback();
302-
p.converters = converters;
303-
p.callable = callable;
304-
return p;
292+
thunk.setfunc = dict.setfunc;
293+
thunk.ffi_restype = dict.ffi_type_pointer;
294+
}
295+
TruffleString signatureStr = FFIType.buildNFISignature(thunk.atypes, thunk.ffi_restype, true);
296+
Source source = Source.newBuilder(J_NFI_LANGUAGE, signatureStr.toJavaStringUncached(), "<ctypes callback>").build();
297+
Object nfiSignature = PythonContext.get(this).getEnv().parseInternal(source).call();
298+
thunk.pcl_exec = SignatureLibrary.getUncached().createClosure(nfiSignature, new CThunkObject.CtypeCallback(thunk));
299+
thunk.pcl_write = thunk.pcl_exec;
300+
thunk.converters = converters;
301+
thunk.callable = callable;
302+
return thunk;
305303
}
306304
}
307305

0 commit comments

Comments
 (0)