From d15bbbc4591c17a60bacfb7bec5cf2afdfff0504 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 23 Jun 2026 11:40:21 +0200 Subject: [PATCH 1/7] Properly read errno/GetLastError using FFM API --- .../python/annotations/DowncallSignature.java | 2 + .../processor/CApiBuiltinsProcessor.java | 79 ++++- .../GenerateNativeDowncallsProcessor.java | 53 ++- .../NativeDowncallMethodHandleGenerator.java | 7 +- .../python/runtime/NativePosixSupport.java | 331 +++++++++--------- .../nativeaccess/NativeAccessSupport.java | 44 ++- .../NativeAccessSupportJdk21.java | 17 +- .../runtime/nativeaccess/NativeContext.java | 68 ++-- 8 files changed, 373 insertions(+), 228 deletions(-) diff --git a/graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/DowncallSignature.java b/graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/DowncallSignature.java index 274e9210bf..c0a74428eb 100644 --- a/graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/DowncallSignature.java +++ b/graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/DowncallSignature.java @@ -55,4 +55,6 @@ Class retConversion() default void.class; Class[] argConversions() default {}; + + boolean captureCallState() default false; } diff --git a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/CApiBuiltinsProcessor.java b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/CApiBuiltinsProcessor.java index c19609436f..6fd1c15288 100644 --- a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/CApiBuiltinsProcessor.java +++ b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/CApiBuiltinsProcessor.java @@ -1600,13 +1600,24 @@ private void generateNativeAccessSupport(Element[] origins) throws IOException { lines.add("import java.lang.invoke.MethodHandle;"); lines.add("import java.lang.invoke.MethodHandles;"); lines.add("import java.lang.invoke.MethodType;"); + lines.add("import java.lang.invoke.VarHandle;"); + lines.add("import java.util.ArrayList;"); + lines.add("import java.util.List;"); lines.add("import java.util.OptionalLong;"); lines.add(""); lines.add("import static com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere;"); + lines.add("import com.oracle.graal.python.PythonLanguage;"); lines.add("import " + NativeSimpleType.class.getCanonicalName() + ";"); + lines.add("import com.oracle.graal.python.annotations.PythonOS;"); + lines.add("import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;"); lines.add(""); lines.add("public final class " + NATIVE_ACCESS_SUPPORT_IMPL_CLASS_NAME + " extends " + NATIVE_ACCESS_SUPPORT_CLASS_NAME + " {"); lines.add(" private static final MethodHandle OF_ADDRESS;"); + lines.add(" private static final boolean WINDOWS = PythonLanguage.getPythonOS() == PythonOS.PLATFORM_WIN32;"); + lines.add(" private static final MemoryLayout CAPTURE_STATE_LAYOUT = Linker.Option.captureStateLayout();"); + lines.add(" private static final VarHandle ERRNO = captureStateVarHandle(\"errno\");"); + lines.add(" private static final VarHandle GET_LAST_ERROR = WINDOWS ? captureStateVarHandle(\"GetLastError\") : null;"); + lines.add(" private static final Linker.Option CAPTURE_CALL_STATE_OPTION = WINDOWS ? Linker.Option.captureCallState(\"errno\", \"GetLastError\", \"WSAGetLastError\") : Linker.Option.captureCallState(\"errno\");"); lines.add(""); lines.add(" static {"); lines.add(" try {"); @@ -1616,6 +1627,10 @@ private void generateNativeAccessSupport(Element[] origins) throws IOException { lines.add(" }"); lines.add(" }"); lines.add(""); + lines.add(" private static VarHandle captureStateVarHandle(String stateName) {"); + lines.add(" return CAPTURE_STATE_LAYOUT.varHandle(MemoryLayout.PathElement.groupElement(stateName));"); + lines.add(" }"); + lines.add(""); lines.add(" @Override"); lines.add(" protected Object createArenaImpl() {"); lines.add(" return Arena.ofShared();"); @@ -1640,15 +1655,41 @@ private void generateNativeAccessSupport(Element[] origins) throws IOException { lines.add(""); lines.add(" @Override"); lines.add(" @SuppressWarnings(\"restricted\")"); - lines.add(" protected MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical) {"); - lines.add(" FunctionDescriptor functionDescriptor = createFunctionDescriptor(methodType);"); - lines.add(" Linker.Option[] options = critical ? new Linker.Option[] { Linker.Option.critical(false) } : new Linker.Option[0];"); - lines.add(" MethodHandle methodHandle = Linker.nativeLinker().downcallHandle(functionDescriptor, options);"); + lines.add(" protected MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical, boolean captureCallState) {"); + lines.add(" FunctionDescriptor functionDescriptor = createFunctionDescriptor(methodType, captureCallState ? 2 : 1);"); + lines.add(" List options = new ArrayList<>();"); + lines.add(" if (critical) {"); + lines.add(" options.add(Linker.Option.critical(false));"); + lines.add(" }"); + lines.add(" if (captureCallState) {"); + lines.add(" options.add(CAPTURE_CALL_STATE_OPTION);"); + lines.add(" }"); + lines.add(" MethodHandle methodHandle = Linker.nativeLinker().downcallHandle(functionDescriptor, options.toArray(Linker.Option[]::new));"); lines.add(" methodHandle = MethodHandles.filterArguments(methodHandle, 0, OF_ADDRESS);"); lines.add(" return methodHandle.asType(methodType);"); lines.add(" }"); lines.add(""); lines.add(" @Override"); + lines.add(" protected Object createCapturedCallStateImpl(Object arena) {"); + lines.add(" return ((Arena) arena).allocate(CAPTURE_STATE_LAYOUT);"); + lines.add(" }"); + lines.add(""); + lines.add(" @TruffleBoundary"); + lines.add(" @Override"); + lines.add(" protected int readCapturedErrnoImpl(Object capturedCallState) {"); + lines.add(" return (int) ERRNO.get((MemorySegment) capturedCallState, 0L);"); + lines.add(" }"); + lines.add(""); + lines.add(" @TruffleBoundary"); + lines.add(" @Override"); + lines.add(" protected int readCapturedGetLastErrorImpl(Object capturedCallState) {"); + lines.add(" if (GET_LAST_ERROR == null) {"); + lines.add(" throw shouldNotReachHere(\"GetLastError is only captured on Windows\");"); + lines.add(" }"); + lines.add(" return (int) GET_LAST_ERROR.get((MemorySegment) capturedCallState, 0L);"); + lines.add(" }"); + lines.add(""); + lines.add(" @Override"); lines.add(" @SuppressWarnings(\"restricted\")"); lines.add(" protected long createClosureImpl(MethodHandle staticMethodHandle, NativeSimpleType resType, NativeSimpleType[] argTypes, Object arena) {"); lines.add(" FunctionDescriptor functionDescriptor = createFunctionDescriptor(resType, argTypes);"); @@ -1668,11 +1709,11 @@ private void generateNativeAccessSupport(Element[] origins) throws IOException { lines.add(" return resType == NativeSimpleType.VOID ? FunctionDescriptor.ofVoid(argLayouts) : FunctionDescriptor.of(asLayout(resType), argLayouts);"); lines.add(" }"); lines.add(""); - lines.add(" private static FunctionDescriptor createFunctionDescriptor(MethodType methodType) {"); + lines.add(" private static FunctionDescriptor createFunctionDescriptor(MethodType methodType, int firstNativeArg) {"); lines.add(" Class[] parameterTypes = methodType.parameterArray();"); - lines.add(" MemoryLayout[] argLayouts = new MemoryLayout[parameterTypes.length - 1];"); - lines.add(" for (int i = 1; i < parameterTypes.length; i++) {"); - lines.add(" argLayouts[i - 1] = asLayout(parameterTypes[i]);"); + lines.add(" MemoryLayout[] argLayouts = new MemoryLayout[parameterTypes.length - firstNativeArg];"); + lines.add(" for (int i = firstNativeArg; i < parameterTypes.length; i++) {"); + lines.add(" argLayouts[i - firstNativeArg] = asLayout(parameterTypes[i]);"); lines.add(" }"); lines.add(" Class returnType = methodType.returnType();"); lines.add(" return returnType == void.class ? FunctionDescriptor.ofVoid(argLayouts) : FunctionDescriptor.of(asLayout(returnType), argLayouts);"); @@ -1750,7 +1791,27 @@ private void generateDummyNativeAccessSupport(Element[] origins) throws IOExcept lines.add(" }"); lines.add(""); lines.add(" @Override"); - lines.add(" protected MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical) {"); + lines.add(" protected MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical, boolean captureCallState) {"); + lines.add(" throw unsupported();"); + lines.add(" }"); + lines.add(""); + lines.add(" @Override"); + lines.add(" protected Object createCapturedCallStateImpl() {"); + lines.add(" throw unsupported();"); + lines.add(" }"); + lines.add(""); + lines.add(" @Override"); + lines.add(" protected Object getCapturedCallStateSegmentImpl(Object state) {"); + lines.add(" throw unsupported();"); + lines.add(" }"); + lines.add(""); + lines.add(" @Override"); + lines.add(" protected int readCapturedErrnoImpl(Object state) {"); + lines.add(" throw unsupported();"); + lines.add(" }"); + lines.add(""); + lines.add(" @Override"); + lines.add(" protected int readCapturedGetLastErrorImpl(Object state) {"); lines.add(" throw unsupported();"); lines.add(" }"); lines.add(""); diff --git a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java index ede35d6f5f..e1247cf456 100644 --- a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java +++ b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java @@ -63,9 +63,12 @@ import com.oracle.graal.python.annotations.NativeSimpleType; public class GenerateNativeDowncallsProcessor extends AbstractProcessor { - private record NativeDowncallDesc(String name, String symbolName, NativeSimpleType returnType, List argumentTypes, List argumentNames) { + private record NativeDowncallDesc(String name, NativeSimpleType returnType, List argumentTypes, List argumentNames, boolean captureCallState) { } + private static final String CAPTURE_CALL_STATE_FIELD = "callState"; + private static final String NATIVE_MEMORY_SEGMENT_CLASS_FIELD = "NATIVE_MEMORY_SEGMENT_CLASS"; + @Override public Set getSupportedAnnotationTypes() { return Set.of(DowncallSignature.class.getName()); @@ -124,6 +127,9 @@ private void generateInvoker(TypeElement invokerElement) throws IOException, Pro throw error(invokerElement, "Annotated class does not declare any downcalls"); } + // Indicates if any of the annotations wants to capture the state. In this case, we need to generate appropriate code. + boolean hasCapturedCallStates = hasCapturedCallStates(downcalls); + String packageName = processingEnv.getElementUtils().getPackageOf(invokerElement).getQualifiedName().toString(); String invokerQualifiedName = invokerElement.getQualifiedName().toString(); String invokerTypeRef = invokerQualifiedName.startsWith(packageName + ".") ? invokerQualifiedName.substring(packageName.length() + 1) : invokerQualifiedName; @@ -135,9 +141,11 @@ private void generateInvoker(TypeElement invokerElement) throws IOException, Pro lines.add("// Generated by annotation processor: " + getClass().getName()); lines.add("package " + packageName + ";"); lines.add(""); + lines.add("import java.lang.foreign.MemorySegment;"); lines.add("import java.lang.invoke.MethodHandle;"); lines.add("import java.lang.invoke.MethodType;"); lines.add("import java.util.concurrent.atomic.AtomicLongArray;"); + lines.add("import java.util.List;"); lines.add(""); lines.add("import com.oracle.graal.python.runtime.nativeaccess.NativeAccessSupport;"); lines.add("import com.oracle.graal.python.runtime.nativeaccess.NativeLibrary;"); @@ -145,18 +153,25 @@ private void generateInvoker(TypeElement invokerElement) throws IOException, Pro lines.add("import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;"); lines.add(""); lines.add("final class " + className + " extends " + invokerTypeRef + " {"); + lines.add(" private static final Class " + NATIVE_MEMORY_SEGMENT_CLASS_FIELD + " = MemorySegment.NULL.getClass();"); lines.add(" private final PythonContext context;"); lines.add(" private final AtomicLongArray cachedFunctions = new AtomicLongArray(" + downcalls.size() + ");"); lines.add(" private volatile NativeLibrary nativeLibrary;"); + if (hasCapturedCallStates) { + lines.add(" private final ThreadLocal " + CAPTURE_CALL_STATE_FIELD + ";"); + } lines.add(""); for (NativeDowncallDesc downcall : downcalls) { - NativeDowncallMethodHandleGenerator.emitMethodHandleField(lines, methodHandleName(downcall.name), downcall.returnType, downcall.argumentTypes); + NativeDowncallMethodHandleGenerator.emitMethodHandleField(lines, methodHandleName(downcall.name), downcall.returnType, downcall.argumentTypes, false, downcall.captureCallState); } lines.add(""); lines.add(" " + className + "(PythonContext context) {"); lines.add(" this.context = context;"); + if (hasCapturedCallStates) { + lines.add(" this." + CAPTURE_CALL_STATE_FIELD + " = ThreadLocal.withInitial(() -> context.ensureNativeContext().getCapturedCallStateTL().get());"); + } lines.add(" }"); for (int i = 0; i < downcalls.size(); i++) { @@ -229,13 +244,12 @@ private static NativeDowncallDesc extractDowncall(ExecutableElement method) thro List argumentTypes = List.of(argTypes); List argumentNames = extractArgumentNames(method); - String symbolName = method.getSimpleName().toString(); return new NativeDowncallDesc( - symbolName, - symbolName, + method.getSimpleName().toString(), annotation.returnType(), argumentTypes, - argumentNames); + argumentNames, + annotation.captureCallState()); } private static List extractArgumentNames(ExecutableElement method) throws ProcessingError { @@ -289,12 +303,12 @@ private static void emitDowncallMethod(List lines, NativeDowncallDesc do lines.add(" @TruffleBoundary(allowInlining = true, transferToInterpreterOnException = false)"); lines.add(" @Override"); lines.add(" " + nativeSimpleTypeToJavaType(downcall.returnType) + " " + downcall.name + "(" + typedArgs(downcall.argumentTypes, downcall.argumentNames) + ") {"); - lines.add(" long functionPointer = lookup(" + functionIndex + ", " + stringLiteral(downcall.symbolName) + ");"); + lines.add(" long functionPointer = lookup(" + functionIndex + ", " + stringLiteral(downcall.name) + ");"); lines.add(" try {"); if (NativeSimpleType.VOID == downcall.returnType) { - lines.add(" " + methodHandleName(downcall.name) + ".invokeExact(" + invokeArgs(downcall.argumentNames) + ");"); + lines.add(" " + methodHandleName(downcall.name) + ".invokeExact(" + invokeArgs(downcall) + ");"); } else { - lines.add(" return (" + nativeSimpleTypeToJavaType(downcall.returnType) + ") " + methodHandleName(downcall.name) + ".invokeExact(" + invokeArgs(downcall.argumentNames) + ");"); + lines.add(" return (" + nativeSimpleTypeToJavaType(downcall.returnType) + ") " + methodHandleName(downcall.name) + ".invokeExact(" + invokeArgs(downcall) + ");"); } lines.add(" } catch (Throwable t) {"); lines.add(" throw CompilerDirectives.shouldNotReachHere(t);"); @@ -314,12 +328,27 @@ private static String typedArgs(List argTypes, List ar return String.join(", ", args); } - private static String invokeArgs(List argNames) { - String args = String.join(", ", argNames); - return args.isEmpty() ? "functionPointer" : "functionPointer, " + args; + private static String invokeArgs(NativeDowncallDesc downcall) { + List allArgs = new ArrayList<>(); + allArgs.add("functionPointer"); + if (downcall.captureCallState) { + String capturedCallState = String.format("%s.cast(%s.get())", NATIVE_MEMORY_SEGMENT_CLASS_FIELD, CAPTURE_CALL_STATE_FIELD); + allArgs.add(capturedCallState); + } + allArgs.addAll(downcall.argumentNames); + return String.join(", ", allArgs); } private static String stringLiteral(String value) { return "\"" + value.replace("\\", "\\\\").replace("\"", "\\\"") + "\""; } + + private static boolean hasCapturedCallStates(List downcalls) { + for (NativeDowncallDesc downcall : downcalls) { + if (downcall.captureCallState) { + return true; + } + } + return false; + } } diff --git a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/NativeDowncallMethodHandleGenerator.java b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/NativeDowncallMethodHandleGenerator.java index e31e059c70..eab9afaf75 100644 --- a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/NativeDowncallMethodHandleGenerator.java +++ b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/NativeDowncallMethodHandleGenerator.java @@ -95,13 +95,16 @@ static void emitMethodHandleField(List lines, String fieldName, String r "MethodType.methodType(" + toClassLiteral(returnType) + ", " + String.join(", ", methodTypeArgs) + "), false);"); } - static void emitMethodHandleField(List lines, String fieldName, NativeSimpleType returnType, List argTypes) { + static void emitMethodHandleField(List lines, String fieldName, NativeSimpleType returnType, List argTypes, boolean critical, boolean captureCallState) { List methodTypeArgs = new ArrayList<>(); methodTypeArgs.add("long.class"); + if (captureCallState) { + methodTypeArgs.add("MemorySegment.class"); + } for (NativeSimpleType argType : argTypes) { methodTypeArgs.add(toClassLiteral(argType)); } lines.add(" private static final MethodHandle " + fieldName + " = NativeAccessSupport.createDowncallHandle(" + - "MethodType.methodType(" + toClassLiteral(returnType) + ", " + String.join(", ", methodTypeArgs) + "), false);"); + "MethodType.methodType(" + toClassLiteral(returnType) + ", " + String.join(", ", methodTypeArgs) + "), " + critical + ", " + captureCallState + ");"); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java index 3be698bca1..312cccf330 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java @@ -144,10 +144,8 @@ import sun.misc.Unsafe; -/** - * Implementation that invokes the native POSIX support library through generated native-access - * downcalls. - */ +/** Implementation that invokes the native POSIX support library through generated native-access + * downcalls. */ @ExportLibrary(PosixSupportLibrary.class) public final class NativePosixSupport extends PosixSupport { private static final String SUPPORTING_NATIVE_LIB_NAME = "posix"; @@ -166,419 +164,416 @@ public final class NativePosixSupport extends PosixSupport { private static final Object CRYPT_LOCK = new Object(); abstract static class PosixNativeFunctionInvoker { - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT32}) abstract int init_constants(long out, int len); - @DowncallSignature(returnType = SINT32) - abstract int get_errno(); - - @DowncallSignature(returnType = VOID, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT32}) abstract void set_errno(int errno); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT64, SINT32, SINT32, SINT32, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT64, SINT32, SINT32, SINT32, SINT64}) abstract long call_mmap(long length, int prot, int flags, int fd, long offset); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, SINT64}) abstract int call_munmap(long address, long length); - @DowncallSignature(returnType = VOID, argumentTypes = {SINT64, SINT64, SINT64}) + @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT64, SINT64, SINT64}) abstract void call_msync(long address, long offset, long length); - @DowncallSignature(returnType = VOID, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT32, POINTER, SINT32}) abstract void call_strerror(int error, long buf, int buflen); - @DowncallSignature(returnType = SINT64) + @DowncallSignature(captureCallState = true, returnType = SINT64) abstract long call_getpid(); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_umask(int mask); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) abstract int call_openat(int dirFd, long pathname, int flags, int mode); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_close(int fd); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32, POINTER, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32, POINTER, SINT64}) abstract long call_read(int fd, long buf, long count); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32, POINTER, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32, POINTER, SINT64}) abstract long call_write(int fd, long buf, long count); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_dup(int fd); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32}) abstract int call_dup2(int oldfd, int newfd, int inheritable); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_pipe2(long pipefd); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER, SINT32, POINTER, SINT32, SINT64, SINT64, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER, SINT32, POINTER, SINT32, SINT64, SINT64, POINTER}) abstract int call_select(int nfds, long readfds, int readfdsLen, long writefds, int writefdsLen, long errfds, int errfdsLen, long timeoutSec, long timeoutUsec, long selected); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT64, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT64, SINT64}) abstract int call_poll(int fd, int writing, long timeoutSec, long timeoutUsec); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32, SINT64, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32, SINT64, SINT32}) abstract long call_lseek(int fd, long offset, int whence); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT64}) abstract int call_ftruncate(int fd, long length); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT64}) abstract int call_truncate(long path, long length); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_fsync(int fd); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int call_flock(int fd, int operation); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, SINT32, SINT64, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, SINT32, SINT64, SINT64}) abstract int call_fcntl_lock(int fd, int blocking, int lockType, int whence, long start, long length); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER}) abstract int call_fstatat(int dirFd, long path, int followSymlinks, long out); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_fstat(int fd, long out); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER}) abstract int call_statvfs(long path, long out); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_fstatvfs(int fd, long out); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, POINTER, POINTER, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, POINTER, POINTER, POINTER, SINT32}) abstract int call_uname(long sysname, long nodename, long release, long version, long machine, int size); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) abstract int call_unlinkat(int dirFd, long pathname, int rmdir); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER, SINT32}) abstract int call_linkat(int oldDirFd, long oldPath, int newDirFd, long newPath, int flags); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT32, POINTER}) abstract int call_symlinkat(long target, int dirFd, long linkpath); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) abstract int call_mkdirat(int dirFd, long pathname, int mode); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT64}) abstract int call_getcwd(long buf, long size); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_chdir(long path); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_fchdir(int fd); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_isatty(int fd); - @DowncallSignature(returnType = SINT64, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {POINTER}) abstract long call_opendir(long name); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32}) abstract long call_fdopendir(int fd); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64}) abstract int call_closedir(long dirp); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, POINTER, SINT64, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, POINTER, SINT64, POINTER}) abstract int call_readdir(long dirp, long nameBuf, long nameBufSize, long out); - @DowncallSignature(returnType = VOID, argumentTypes = {SINT64}) + @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT64}) abstract void call_rewinddir(long dirp); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER, SINT32}) abstract int call_utimensat(int dirFd, long path, long timespec, int followSymlinks); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_futimens(int fd, long timespec); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_futimes(int fd, long timeval); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER}) abstract int call_lutimes(long filename, long timeval); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER}) abstract int call_utimes(long filename, long timeval); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER}) abstract int call_renameat(int oldDirFd, long oldPath, int newDirFd, long newPath); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32}) abstract int call_faccessat(int dirFd, long path, int mode, int effectiveIds, int followSymlinks); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) abstract int call_fchmodat(int dirFd, long path, int mode, int followSymlinks); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int call_fchmod(int fd, int mode); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT64, SINT64, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT64, SINT64, SINT32}) abstract int call_fchownat(int dirfd, long pathname, long owner, long group, int followSymlinks); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT64, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT64, SINT64}) abstract int call_fchown(int fd, long owner, long group); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32, POINTER, POINTER, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32, POINTER, POINTER, SINT64}) abstract long call_readlinkat(int dirFd, long path, long buf, long size); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int get_inheritable(int fd); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int set_inheritable(int fd, int inheritable); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int get_blocking(int fd); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int set_blocking(int fd, int blocking); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int get_terminal_size(int fd, long size); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_raise(int signal); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_alarm(int seconds); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_getitimer(int which, long currentValue); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_setitimer(int which, long newValue, long oldValue); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int signal_self(int signal); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, SINT32}) abstract int call_kill(long pid, int signal); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, SINT32}) abstract int call_killpg(long pgid, int signal); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT64, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT64, POINTER, SINT32}) abstract long call_waitpid(long pid, long status, int options); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wcoredump(int status); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wifcontinued(int status); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wifstopped(int status); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wifsignaled(int status); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wifexited(int status); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wexitstatus(int status); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wtermsig(int status); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wstopsig(int status); - @DowncallSignature(returnType = SINT64) + @DowncallSignature(captureCallState = true, returnType = SINT64) abstract long call_getuid(); - @DowncallSignature(returnType = SINT64) + @DowncallSignature(captureCallState = true, returnType = SINT64) abstract long call_geteuid(); - @DowncallSignature(returnType = SINT64) + @DowncallSignature(captureCallState = true, returnType = SINT64) abstract long call_getgid(); - @DowncallSignature(returnType = SINT64) + @DowncallSignature(captureCallState = true, returnType = SINT64) abstract long call_getegid(); - @DowncallSignature(returnType = SINT64) + @DowncallSignature(captureCallState = true, returnType = SINT64) abstract long call_getppid(); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT64}) abstract long call_getpgid(long pid); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, SINT64}) abstract int call_setpgid(long pid, long pgid); - @DowncallSignature(returnType = SINT64) + @DowncallSignature(captureCallState = true, returnType = SINT64) abstract long call_getpgrp(); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT64}) abstract long call_getsid(long pid); - @DowncallSignature(returnType = SINT64) + @DowncallSignature(captureCallState = true, returnType = SINT64) abstract long call_setsid(); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, POINTER}) abstract int call_getgroups(long size, long out); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_getrusage(int who, long out); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_openpty(long outvars); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_ctermid(long buf); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32}) abstract int call_setenv(long name, long value, int overwrite); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_unsetenv(long name); - @DowncallSignature(returnType = SINT32, argumentTypes = { + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = { POINTER, POINTER, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, POINTER, SINT64 }) abstract int fork_exec(long data, long offsets, int offsetsLen, int argsPos, int envPos, int cwdPos, int stdinRdFd, int stdinWrFd, int stdoutRdFd, int stdoutWrFd, int stderrRdFd, int stderrWrFd, int errPipeRdFd, int errPipeWrFd, int closeFds, int restoreSignals, int callSetsid, int pgidToSet, int allowVFork, long fdsToKeep, long fdsToKeepLen); - @DowncallSignature(returnType = VOID, argumentTypes = {POINTER, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {POINTER, POINTER, SINT32}) abstract void call_execv(long data, long offsets, int offsetsLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_system(long pathname); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, POINTER, SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, POINTER, SINT32, POINTER}) abstract int call_getpwuid_r(long uid, long buffer, int bufferSize, long output); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, POINTER}) abstract int call_getpwname_r(long name, long buffer, int bufferSize, long output); - @DowncallSignature(returnType = VOID) + @DowncallSignature(captureCallState = true, returnType = VOID) abstract void call_setpwent(); - @DowncallSignature(returnType = VOID) + @DowncallSignature(captureCallState = true, returnType = VOID) abstract void call_endpwent(); - @DowncallSignature(returnType = POINTER, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = POINTER, argumentTypes = {POINTER}) abstract long call_getpwent(long bufferSize); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, POINTER}) abstract int get_getpwent_data(long p, long buffer, int bufferSize, long output); - @DowncallSignature(returnType = SINT64) + @DowncallSignature(captureCallState = true, returnType = SINT64) abstract long get_sysconf_getpw_r_size_max(); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32}) abstract int call_socket(int family, int type, int protocol); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_accept(int sockfd, long addr, long addrLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) abstract int call_bind(int sockfd, long addr, int addrLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) abstract int call_connect(int sockfd, long addr, int addrLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int call_listen(int sockfd, int backlog); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_getpeername(int sockfd, long addr, long addrLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_getsockname(int sockfd, long addr, long addrLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) abstract int call_send(int sockfd, long buf, int len, int flags); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32, POINTER, SINT32}) abstract int call_sendto(int sockfd, long buf, int offset, int len, int flags, long addr, int addrLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) abstract int call_recv(int sockfd, long buf, int len, int flags); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32, POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32, POINTER, POINTER}) abstract int call_recvfrom(int sockfd, long buf, int offset, int len, int flags, long srcAddr, long addrLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int call_shutdown(int sockfd, int how); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, POINTER, POINTER}) abstract int call_getsockopt(int sockfd, int level, int optname, long buf, long bufLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, POINTER, SINT32}) abstract int call_setsockopt(int sockfd, int level, int optname, long buf, int bufLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_inet_addr(long src); - @DowncallSignature(returnType = SINT64, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {POINTER}) abstract long call_inet_aton(long src); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_inet_ntoa(int src, long dst); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_inet_pton(int family, long src, long dst); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER, SINT32}) abstract int call_inet_ntop(int family, long src, long dst, int dstSize); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT64}) abstract int call_gethostname(long buf, long bufLen); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT32, POINTER, SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT32, POINTER, SINT32, POINTER, SINT32, SINT32}) abstract int call_getnameinfo(long addr, int addrLen, long hostBuf, int hostBufLen, long servBuf, int servBufLen, int flags); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, SINT32, SINT32, SINT32, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, SINT32, SINT32, SINT32, POINTER}) abstract int call_getaddrinfo(long node, long service, int family, int sockType, int protocol, int flags, long ptr); - @DowncallSignature(returnType = VOID, argumentTypes = {SINT64}) + @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT64}) abstract void call_freeaddrinfo(long ptr); - @DowncallSignature(returnType = VOID, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT32, POINTER, SINT32}) abstract void call_gai_strerror(int error, long buf, int buflen); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, POINTER, POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, POINTER, POINTER, POINTER}) abstract int get_addrinfo_members(long ptr, long intData, long longData, long addr); - @DowncallSignature(returnType = POINTER, argumentTypes = {POINTER, SINT32, SINT32, SINT32}) + @DowncallSignature(captureCallState = true, returnType = POINTER, argumentTypes = {POINTER, SINT32, SINT32, SINT32}) abstract long call_sem_open(long name, int openFlags, int mode, int value); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_close(long handle); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_unlink(long name); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER}) abstract int call_sem_getvalue(long handle, long value); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_post(long handle); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_wait(long handle); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_trywait(long handle); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT64}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT64}) abstract int call_sem_timedwait(long handle, long deadlineNs); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT64, POINTER}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT64, POINTER}) abstract int call_ioctl_bytes(int fd, long request, long buffer); - @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT64, SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT64, SINT32}) abstract int call_ioctl_int(int fd, long request, int arg); - @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32}) + @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32}) abstract long call_sysconf(int name); @TruffleBoundary @@ -611,11 +606,9 @@ static NativeLibrary loadNativeLibrary(PythonContext context) { if (PythonLanguage.getPythonOS() == PythonOS.PLATFORM_DARWIN) { return context.ensureNativeContext().getDefaultLibrary(); } - /* - * We don't want to link the posix support library against libcrypt, because it might + /* We don't want to link the posix support library against libcrypt, because it might * not be available on the target Linux system and would make the whole support library - * fail to load. Load it dynamically on demand instead. - */ + * fail to load. Load it dynamically on demand instead. */ try { return context.ensureNativeContext().loadLibrary("libcrypt.so", PosixConstants.RTLD_LOCAL.value); } catch (NativeLibraryLoadException e) { @@ -993,7 +986,7 @@ public int[] getTerminalSize(int fd) throws PosixException { public long sysconf(int name) throws PosixException { long result = posixNativeFunctionInvoker.call_sysconf(name); if (result == -1) { - int errno = posixNativeFunctionInvoker.get_errno(); + int errno = getErrno(); if (errno != 0) { throw newPosixException(errno); } @@ -1181,7 +1174,7 @@ public Object getcwd() throws PosixException { buffer = buffer.withLength(findZero(buffer.data)); return buffer; } - int errno = posixNativeFunctionInvoker.get_errno(); + int errno = getErrno(); if (errno != OSErrorEnum.ERANGE.getNumber()) { throw newPosixException(errno); } @@ -1273,7 +1266,7 @@ public Object readdir(Object dirStreamObj) throws PosixException { NativeMemory.free(nativeOut); NativeMemory.free(nativeName); } - int errno = posixNativeFunctionInvoker.get_errno(); + int errno = getErrno(); if (errno == 0) { return null; } @@ -1448,7 +1441,7 @@ public boolean faccessat(int dirFd, Object path, int mode, boolean effectiveIds, NativeMemory.free(pathPtr); } if (ret != 0 && LOGGER.isLoggable(Level.FINE)) { - log(Level.FINE, "faccessat return value: %d, errno: %d", ret, posixNativeFunctionInvoker.get_errno()); + log(Level.FINE, "faccessat return value: %d, errno: %d", ret, getErrno()); } return ret == 0; } @@ -2022,11 +2015,9 @@ private static long addLengthsOfCStrings(long prevLen, Object[] src) throws Over return PythonUtils.addExact(len, src.length); // add space for terminating '\0' } - /** - * Copies null-terminated strings to a buffer {@code data} starting at position {@code offset}, + /** Copies null-terminated strings to a buffer {@code data} starting at position {@code offset}, * and stores the offset of each string to the {@code offsets} array starting at index - * {@code startPos}. - */ + * {@code startPos}. */ private static long encodeCStringArray(byte[] data, long startOffset, long[] offsets, int startPos, Object[] src) { // The code that calculates dataLen already checked that there is no overflow and that all // offsets fit into an int. @@ -2547,14 +2538,12 @@ public TruffleString crypt(TruffleString word, TruffleString salt, @Exclusive @Cached TruffleString.SwitchEncodingNode switchEncodingToUtf8Node, @Exclusive @Cached TruffleString.CopyToByteArrayNode copyToByteArrayNode, @Exclusive @Cached NativeMemory.ZeroTerminatedUtf8ToTruffleStringNode zeroTerminatedUtf8ToTruffleStringNode) throws PosixException { - /* - * From the manpage: Upon successful completion, crypt returns a pointer to a string which + /* From the manpage: Upon successful completion, crypt returns a pointer to a string which * encodes both the hashed passphrase, and the settings that were used to encode it. See * crypt(5) for more detail on the format of hashed passphrases. crypt places its result in * a static storage area, which will be overwritten by subsequent calls to crypt. It is not * safe to call crypt from multiple threads simultaneously. Upon error, it may return a NULL - * pointer or a pointer to an invalid hash, depending on the implementation. - */ + * pointer or a pointer to an invalid hash, depending on the implementation. */ long wordPtr = NULLPTR; long saltPtr = NULLPTR; try { @@ -2599,8 +2588,7 @@ private TruffleString gai_strerror(Node inliningTarget, int errorCode, NativeMem } } - /** - * Provides access to {@code struct addrinfo}. + /** Provides access to {@code struct addrinfo}. * * The layout of native {@code struct addrinfo} is as follows: * @@ -2615,7 +2603,7 @@ private TruffleString gai_strerror(Node inliningTarget, int errorCode, NativeMem * struct sockaddr *ai_addr; // data copied into socketAddress[] * char *ai_canonname; // longData[0] * struct addrinfo *ai_next; // longData[1] - * }; + * }; * } * * @@ -2632,8 +2620,7 @@ private TruffleString gai_strerror(Node inliningTarget, int errorCode, NativeMem * * It is not clear whether it is guaranteed that {@code ai_family} and * {@code ai_addr->sa_family} are always the same. We provide both and use the later when - * decoding the socket address. - */ + * decoding the socket address. */ private static class AddrInfo { private final int[] intData = new int[7]; private final long[] longData = new long[2]; @@ -2969,10 +2956,8 @@ void semUnlink(Object name) throws PosixException { @ExportMessage int semGetValue(long handle) throws PosixException { - /* - * msimacek: It works on Linux, and it doesn't work on Darwin. It might work on some other - * Unix-likes, but it's hard to check, so let's assume it only works on Linux for now - */ + /* msimacek: It works on Linux, and it doesn't work on Darwin. It might work on some other + * Unix-likes, but it's hard to check, so let's assume it only works on Linux for now */ if (PythonLanguage.getPythonOS() != PythonOS.PLATFORM_LINUX) { throw NO_SEM_GETVALUE_EXCEPTION; } @@ -3008,7 +2993,7 @@ void semWait(long handle) throws PosixException { boolean semTryWait(long handle) throws PosixException { int res = posixNativeFunctionInvoker.call_sem_trywait(handle); if (res < 0) { - int errno = posixNativeFunctionInvoker.get_errno(); + int errno = getErrno(); if (errno == OSErrorEnum.EAGAIN.getNumber()) { return false; } @@ -3024,7 +3009,7 @@ boolean semTimedWait(long handle, long deadlineNs, if (PythonLanguage.getPythonOS() == PythonOS.PLATFORM_LINUX) { int res = posixNativeFunctionInvoker.call_sem_timedwait(handle, deadlineNs); if (res < 0) { - int errno = posixNativeFunctionInvoker.get_errno(); + int errno = getErrno(); if (errno == OSErrorEnum.ETIMEDOUT.getNumber()) { return false; } @@ -3337,7 +3322,7 @@ public String toString() { // Helpers private PosixException getErrnoAndThrowPosixException() throws PosixException { - throw newPosixException(posixNativeFunctionInvoker.get_errno()); + throw newPosixException(getErrno()); } @TruffleBoundary @@ -3421,4 +3406,8 @@ private static void log(Level level, String fmt, Object... args) { LOGGER.log(level, String.format(fmt, args)); } } + + private int getErrno() { + return context.ensureNativeContext().getErrno(); + } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupport.java index f0caf3e8d1..32e358c078 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupport.java @@ -109,7 +109,29 @@ static MethodHandle createDowncallHandle(NativeSimpleType resType, NativeSimpleT } public static MethodHandle createDowncallHandle(MethodType methodType, boolean critical) { - return INSTANCE.createDowncallHandleImpl(methodType, critical); + return INSTANCE.createDowncallHandleImpl(methodType, critical, false); + } + + public static MethodHandle createDowncallHandle(MethodType methodType, boolean critical, boolean captureCallState) { + return INSTANCE.createDowncallHandleImpl(methodType, critical, captureCallState); + } + + public static Object createCapturedCallState(Object arena) { + return INSTANCE.createCapturedCallStateImpl(arena); + } + + /** Read value of POSIX's {@code errno} from the captured call state buffer. */ + public static int readCapturedErrno(Object capturedCallStatePtr) { + return INSTANCE.readCapturedErrnoImpl(capturedCallStatePtr); + } + + /** Read value of WinAPI's {@code GetLastError} from the captured call state buffer. */ + public static int readCapturedGetLastError(Object capturedCallStatePtr) { + return INSTANCE.readCapturedGetLastErrorImpl(capturedCallStatePtr); + } + + static MethodHandle createCapturedDowncallHandle(NativeSimpleType resType, NativeSimpleType... argTypes) { + return INSTANCE.createTypedCapturedDowncallHandle(resType, argTypes); } public static boolean isAvailable() { @@ -130,7 +152,17 @@ private MethodHandle createTypedDowncallHandle(NativeSimpleType resType, NativeS for (int i = 0; i < argTypes.length; i++) { parameterTypes[i + 1] = asJavaType(argTypes[i]); } - return createDowncallHandleImpl(MethodType.methodType(asJavaType(resType), parameterTypes), false); + return createDowncallHandleImpl(MethodType.methodType(asJavaType(resType), parameterTypes), false, false); + } + + private MethodHandle createTypedCapturedDowncallHandle(NativeSimpleType resType, NativeSimpleType... argTypes) { + Class[] parameterTypes = new Class[argTypes.length + 2]; + parameterTypes[0] = long.class; + parameterTypes[1] = long.class; + for (int i = 0; i < argTypes.length; i++) { + parameterTypes[i + 2] = asJavaType(argTypes[i]); + } + return createDowncallHandleImpl(MethodType.methodType(asJavaType(resType), parameterTypes), false, true); } protected abstract Object createArenaImpl(); @@ -141,7 +173,13 @@ private MethodHandle createTypedDowncallHandle(NativeSimpleType resType, NativeS protected abstract long lookupDefaultImpl(String name); - protected abstract MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical); + protected abstract MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical, boolean captureCallState); + + protected abstract Object createCapturedCallStateImpl(Object arena); + + protected abstract int readCapturedErrnoImpl(Object capturedCallState); + + protected abstract int readCapturedGetLastErrorImpl(Object capturedCallState); protected abstract long createClosureImpl(MethodHandle staticMethodHandle, NativeSimpleType resType, NativeSimpleType[] argTypes, Object arena); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupportJdk21.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupportJdk21.java index d19c26e267..e725004f2b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupportJdk21.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupportJdk21.java @@ -66,10 +66,25 @@ protected long lookupDefaultImpl(String name) { } @Override - protected MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical) { + protected MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical, boolean captureCallState) { return unsupportedDowncallHandle(methodType); } + @Override + protected Object createCapturedCallStateImpl(Object arena) { + throw unsupported(); + } + + @Override + protected int readCapturedErrnoImpl(Object state) { + throw unsupported(); + } + + @Override + protected int readCapturedGetLastErrorImpl(Object state) { + throw unsupported(); + } + @Override protected long createClosureImpl(MethodHandle staticMethodHandle, NativeSimpleType resType, NativeSimpleType[] argTypes, Object arena) { throw unsupported(); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeContext.java index 97e7aa5947..c6af81779d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeContext.java @@ -40,11 +40,14 @@ */ package com.oracle.graal.python.runtime.nativeaccess; +import static com.oracle.graal.python.annotations.NativeSimpleType.POINTER; +import static com.oracle.graal.python.annotations.NativeSimpleType.SINT32; +import static com.oracle.graal.python.annotations.NativeSimpleType.SINT64; + import java.lang.invoke.MethodHandle; import java.util.concurrent.ConcurrentLinkedQueue; import com.oracle.graal.python.PythonLanguage; -import com.oracle.graal.python.annotations.NativeSimpleType; import com.oracle.graal.python.annotations.PythonOS; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -67,6 +70,7 @@ public final class NativeContext { private final ConcurrentLinkedQueue libraries = new ConcurrentLinkedQueue<>(); private final NativeLibrary defaultLibrary; + private final ThreadLocal callState; final Object arena; public static NativeContext create() { @@ -77,6 +81,7 @@ public static NativeContext create() { NativeContext() { arena = NativeAccessSupport.createArena(); defaultLibrary = isWindows() ? null : new NativeLibrary(this, getPosixDefaultLibraryHandle()); + callState = ThreadLocal.withInitial(() -> NativeAccessSupport.createCapturedCallState(arena)); } public void close() { @@ -106,7 +111,8 @@ public NativeLibrary loadLibrary(String name, int flags) throws NativeLibraryLoa try { if (isWindows()) { int callFlags = sanitizeWindowsLoadLibraryFlags(flags) | WINDOWS_DEFAULT_LOAD_LIBRARY_FLAGS; - lib = (long) LOAD_LIBRARY_EX.invokeExact(loadLibraryExPtr, nativeName, 0L, callFlags); + Object callStateBuffer = callState.get(); + lib = (long) LOAD_LIBRARY_EX_CAPTURED.invokeExact(loadLibraryExPtr, callStateBuffer, nativeName, 0L, callFlags); } else { int callFlags = flags; if ((callFlags & (RTLD_LAZY | RTLD_NOW)) == 0) { @@ -120,7 +126,7 @@ public NativeLibrary loadLibrary(String name, int flags) throws NativeLibraryLoa NativeMemory.free(nativeName); } if (lib == 0) { - throw createLoadLibraryException(); + throw createLoadLibraryException(isWindows() ? getLastError() : 0); } NativeLibrary library = new NativeLibrary(this, lib); libraries.add(library); @@ -163,17 +169,14 @@ private static boolean isWindows() { private static final long RTLD_DEFAULT_LINUX = 0L; private static final long RTLD_DEFAULT_DARWIN = -2L; - private static final MethodHandle DLOPEN = NativeAccessSupport.createDowncallHandle(NativeSimpleType.SINT64, NativeSimpleType.POINTER, NativeSimpleType.SINT32); - private static final MethodHandle DLCLOSE = NativeAccessSupport.createDowncallHandle(NativeSimpleType.SINT32, NativeSimpleType.SINT64); - private static final MethodHandle DLSYM = NativeAccessSupport.createDowncallHandle(NativeSimpleType.SINT64, NativeSimpleType.SINT64, NativeSimpleType.POINTER); - private static final MethodHandle LOAD_LIBRARY_EX = NativeAccessSupport.createDowncallHandle(NativeSimpleType.SINT64, NativeSimpleType.POINTER, NativeSimpleType.POINTER, - NativeSimpleType.SINT32); - private static final MethodHandle FREE_LIBRARY = NativeAccessSupport.createDowncallHandle(NativeSimpleType.SINT32, NativeSimpleType.SINT64); - private static final MethodHandle GET_PROC_ADDRESS = NativeAccessSupport.createDowncallHandle(NativeSimpleType.SINT64, NativeSimpleType.SINT64, NativeSimpleType.POINTER); - private static final MethodHandle GET_LAST_ERROR = NativeAccessSupport.createDowncallHandle(NativeSimpleType.SINT32); - private static final MethodHandle FORMAT_MESSAGE = NativeAccessSupport.createDowncallHandle(NativeSimpleType.SINT32, NativeSimpleType.SINT32, NativeSimpleType.POINTER, NativeSimpleType.SINT32, - NativeSimpleType.SINT32, NativeSimpleType.POINTER, NativeSimpleType.SINT32, NativeSimpleType.POINTER); - private static final MethodHandle DLERROR = NativeAccessSupport.createDowncallHandle(NativeSimpleType.SINT64); + private static final MethodHandle DLOPEN = NativeAccessSupport.createDowncallHandle(SINT64, POINTER, SINT32); + private static final MethodHandle DLCLOSE = NativeAccessSupport.createDowncallHandle(SINT32, SINT64); + private static final MethodHandle DLSYM = NativeAccessSupport.createDowncallHandle(SINT64, SINT64, POINTER); + private static final MethodHandle FREE_LIBRARY = NativeAccessSupport.createDowncallHandle(SINT32, SINT64); + private static final MethodHandle GET_PROC_ADDRESS = NativeAccessSupport.createDowncallHandle(SINT64, SINT64, POINTER); + private static final MethodHandle FORMAT_MESSAGE = NativeAccessSupport.createDowncallHandle(SINT32, SINT32, POINTER, SINT32, SINT32, POINTER, SINT32, POINTER); + private static final MethodHandle DLERROR = NativeAccessSupport.createDowncallHandle(SINT64); + private static final MethodHandle LOAD_LIBRARY_EX_CAPTURED = isWindows() ? NativeAccessSupport.createCapturedDowncallHandle(SINT64, POINTER, POINTER, SINT32) : null; private static long dlopenPtr; private static long dlclosePtr; @@ -182,7 +185,6 @@ private static boolean isWindows() { private static long loadLibraryExPtr; private static long freeLibraryPtr; private static long getProcAddressPtr; - private static long getLastErrorPtr; private static long formatMessagePtr; private static Object windowsLookupArena; private static NativeLibraryLookup windowsLookup; @@ -192,8 +194,8 @@ private static void ensureLoader() throws UnsupportedOperationException { if (loadLibraryExPtr != 0) { assert freeLibraryPtr != 0; assert getProcAddressPtr != 0; - assert getLastErrorPtr != 0; assert formatMessagePtr != 0; + assert LOAD_LIBRARY_EX_CAPTURED != null; return; } if (windowsLookup == null) { @@ -203,7 +205,6 @@ private static void ensureLoader() throws UnsupportedOperationException { loadLibraryExPtr = NativeAccessSupport.lookupSymbol(windowsLookup, "LoadLibraryExW"); freeLibraryPtr = NativeAccessSupport.lookupSymbol(windowsLookup, "FreeLibrary"); getProcAddressPtr = NativeAccessSupport.lookupSymbol(windowsLookup, "GetProcAddress"); - getLastErrorPtr = NativeAccessSupport.lookupSymbol(windowsLookup, "GetLastError"); formatMessagePtr = NativeAccessSupport.lookupSymbol(windowsLookup, "FormatMessageW"); return; } @@ -218,14 +219,13 @@ private static int sanitizeWindowsLoadLibraryFlags(int flags) { } @TruffleBoundary - private static NativeLibraryLoadException createLoadLibraryException() { + private static NativeLibraryLoadException createLoadLibraryException(int windowsErrorCode) { if (isWindows()) { - int errorCode = getLastError(); - String detail = formatWindowsError(errorCode); + String detail = formatWindowsError(windowsErrorCode); if (detail == null || detail.isBlank()) { - return new NativeLibraryLoadException("Windows error " + errorCode); + return new NativeLibraryLoadException("Windows error " + windowsErrorCode); } - return new NativeLibraryLoadException("Windows error " + errorCode + ": " + detail); + return new NativeLibraryLoadException("Windows error " + windowsErrorCode + ": " + detail); } String detail = getDlError(); if (detail == null || detail.isBlank()) { @@ -234,14 +234,6 @@ private static NativeLibraryLoadException createLoadLibraryException() { return new NativeLibraryLoadException(detail); } - private static int getLastError() { - try { - return (int) GET_LAST_ERROR.invokeExact(getLastErrorPtr); - } catch (Throwable e) { - throw CompilerDirectives.shouldNotReachHere(e); - } - } - private static String getDlError() { try { long ptr = (long) DLERROR.invokeExact(dlerrorPtr); @@ -280,4 +272,20 @@ private static long getPosixDefaultLibraryHandle() { default -> throw new UnsupportedOperationException("Default library is only available on POSIX platforms."); }; } + + public ThreadLocal getCapturedCallStateTL() { + return callState; + } + + /** Get the value of {@code errno} captured by the last downcall which captures it. The capture buffer is thread-local, so no races can happen. */ + @TruffleBoundary(allowInlining = true) + public int getErrno() { + return NativeAccessSupport.readCapturedErrno(callState.get()); + } + + /** Get the value of WinAPI's {@code GetLastError} captured by the last downcall which captures it. The capture buffer is thread-local, so no races can happen. */ + @TruffleBoundary(allowInlining = true) + public int getLastError() { + return NativeAccessSupport.readCapturedGetLastError(callState.get()); + } } From 8925aab249fa73ea6b11a1aa4d1e818964735e9f Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 23 Jun 2026 15:01:09 +0200 Subject: [PATCH 2/7] Reset errno in native --- .../graal/python/runtime/NativePosixSupport.java | 9 --------- graalpython/python-libposix/src/posix.c | 14 ++++++-------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java index 312cccf330..8b7e5eab41 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java @@ -167,9 +167,6 @@ abstract static class PosixNativeFunctionInvoker { @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT32}) abstract int init_constants(long out, int len); - @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT32}) - abstract void set_errno(int errno); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT64, SINT32, SINT32, SINT32, SINT64}) abstract long call_mmap(long length, int prot, int flags, int fd, long offset); @@ -737,7 +734,6 @@ public Buffer read(int fd, long length) throws PosixException { Buffer buffer = Buffer.allocate(count); long nativeBuffer = NativeMemory.mallocByteArrayOrNull(count); try { - posixNativeFunctionInvoker.set_errno(0); long n = posixNativeFunctionInvoker.call_read(fd, nativeBuffer, count); if (n < 0) { throw getErrnoAndThrowPosixException(); @@ -754,7 +750,6 @@ public long write(int fd, Buffer data) throws PosixException { long nativeBuffer = NativeMemory.mallocByteArrayOrNull(data.length); try { NativeMemory.writeByteArrayElements(nativeBuffer, 0, data.data, 0, (int) data.length); - posixNativeFunctionInvoker.set_errno(0); long n = posixNativeFunctionInvoker.call_write(fd, nativeBuffer, data.length); if (n < 0) { throw getErrnoAndThrowPosixException(); @@ -2242,7 +2237,6 @@ public int send(int sockfd, byte[] buf, int offset, int len, int flags) throws P long nativeBuffer = NativeMemory.mallocByteArrayOrNull(len); try { NativeMemory.writeByteArrayElements(nativeBuffer, 0, buf, offset, len); - posixNativeFunctionInvoker.set_errno(0); int result = posixNativeFunctionInvoker.call_send(sockfd, nativeBuffer, len, flags); if (result == -1) { throw getErrnoAndThrowPosixException(); @@ -2265,7 +2259,6 @@ public int sendto(int sockfd, byte[] buf, int offset, int len, int flags, Univer NativeMemory.writeByteArrayElements(nativeBuffer, 0, buf, offset, len); nativeDestAddr = NativeMemory.mallocByteArrayOrNull(destAddrLen); NativeMemory.writeByteArrayElements(nativeDestAddr, 0, destAddr.data, 0, destAddrLen); - posixNativeFunctionInvoker.set_errno(0); int result = posixNativeFunctionInvoker.call_sendto(sockfd, nativeBuffer, 0, len, flags, nativeDestAddr, destAddrLen); if (result == -1) { throw getErrnoAndThrowPosixException(); @@ -2282,7 +2275,6 @@ public int recv(int sockfd, byte[] buf, int offset, int len, int flags) throws P checkBounds(buf, offset, len); long nativeBuffer = NativeMemory.mallocByteArrayOrNull(len); try { - posixNativeFunctionInvoker.set_errno(0); int result = posixNativeFunctionInvoker.call_recv(sockfd, nativeBuffer, len, flags); if (result == -1) { throw getErrnoAndThrowPosixException(); @@ -2305,7 +2297,6 @@ public RecvfromResult recvfrom(int sockfd, byte[] buf, int offset, int len, int nativeBuffer = NativeMemory.mallocByteArrayOrNull(len); nativeSrcAddr = NativeMemory.mallocByteArray(srcAddr.data.length); nativeAddrLen = NativeMemory.mallocIntArray(1); - posixNativeFunctionInvoker.set_errno(0); int result = posixNativeFunctionInvoker.call_recvfrom(sockfd, nativeBuffer, 0, len, flags, nativeSrcAddr, nativeAddrLen); if (result == -1) { throw getErrnoAndThrowPosixException(); diff --git a/graalpython/python-libposix/src/posix.c b/graalpython/python-libposix/src/posix.c index 12893a061c..0420c5c119 100644 --- a/graalpython/python-libposix/src/posix.c +++ b/graalpython/python-libposix/src/posix.c @@ -134,10 +134,12 @@ int32_t call_close(int32_t fd) { } int64_t call_read(int32_t fd, void *buf, uint64_t count) { + errno = 0; return read(fd, buf, count); } int64_t call_write(int32_t fd, void *buf, uint64_t count) { + errno = 0; return write(fd, buf, count); } @@ -876,22 +878,26 @@ int32_t call_getsockname(int32_t sockfd, int8_t *addr, int32_t *addr_len) { //TODO len should be size_t, retval should be ssize_t int32_t call_send(int32_t sockfd, void *buf, int32_t len, int32_t flags) { + errno = 0; return send(sockfd, buf, len, flags); } int32_t call_sendto(int32_t sockfd, void *buf, int32_t offset, int32_t len, int32_t flags, int8_t *addr, int32_t addr_len) { struct sockaddr_storage sa; memcpy(&sa, addr, addr_len); + errno = 0; return sendto(sockfd, buf + offset, len, flags, (struct sockaddr *) &sa, addr_len); } int32_t call_recv(int32_t sockfd, void *buf, int32_t len, int32_t flags) { + errno = 0; return recv(sockfd, buf, len, flags); } int32_t call_recvfrom(int32_t sockfd, void *buf, int32_t offset, int32_t len, int32_t flags, int8_t *src_addr, int32_t *addr_len) { struct sockaddr_storage sa; socklen_t l = sizeof(sa); + errno = 0; int res = recvfrom(sockfd, buf + offset, len, flags, (struct sockaddr *) &sa, &l); if (res != -1) { assert(l <= sizeof(sockaddr_storage)); // l is small enough to be representable by int32_t... @@ -1182,14 +1188,6 @@ int64_t call_sysconf(int32_t name) { return sysconf(name); } -int32_t get_errno() { - return errno; -} - -void set_errno(int e) { - errno = e; -} - #ifdef _WIN32 #define unix_or_0(x) 0 #else From ca03c3901f2786b88c8000d87a093dd73dcd0be0 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Wed, 24 Jun 2026 11:09:51 +0200 Subject: [PATCH 3/7] Do custom errno capturing in NativePosixSupport --- .../src/tests/test_posix.py | 29 ++ .../python/runtime/NativePosixSupport.java | 324 +++++++++--------- .../graal/python/runtime/PythonContext.java | 2 + .../python-libposix/src/errno_capture.h | 69 ++++ graalpython/python-libposix/src/fork_exec.c | 10 +- graalpython/python-libposix/src/posix.c | 282 +++++++++------ 6 files changed, 434 insertions(+), 282 deletions(-) create mode 100644 graalpython/python-libposix/src/errno_capture.h diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_posix.py b/graalpython/com.oracle.graal.python.test/src/tests/test_posix.py index 6511da2dca..0bd4a412a8 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_posix.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_posix.py @@ -270,6 +270,19 @@ def test_open_bytes_path(self): except Exception: pass + def test_failed_read_write_errno(self): + read_fd, write_fd = os.pipe() + os.close(read_fd) + os.close(write_fd) + + with self.assertRaises(OSError) as read_error: + os.read(read_fd, 1) + self.assertEqual(errno.EBADF, read_error.exception.errno) + + with self.assertRaises(OSError) as write_error: + os.write(write_fd, b'x') + self.assertEqual(errno.EBADF, write_error.exception.errno) + def test_fd_converter(self): class MyInt(int): def fileno(self): return 0 @@ -554,6 +567,11 @@ def test_scandir_empty(self): with os.scandir(TEST_FULL_PATH1) as dir: self.assertEqual(0, len([entry for entry in dir])) + def test_scandir_empty_repeated_eof(self): + with os.scandir(TEST_FULL_PATH1) as dir: + self.assertRaises(StopIteration, next, dir) + self.assertRaises(StopIteration, next, dir) + def test_listdir_empty(self): self.assertEqual([], os.listdir(TEST_FULL_PATH1)) @@ -948,6 +966,17 @@ def sysconf_max(name): self.assertGreaterEqual(os.sysconf('SC_PHYS_PAGES'), 1) self.assertGreaterEqual(os.sysconf('SC_NPROCESSORS_CONF'), 1) + def test_sysconf_valid_minus_one(self): + for name in os.sysconf_names: + try: + value = os.sysconf(name) + except OSError: + continue + if value == -1: + self.assertEqual(-1, os.sysconf(name)) + return + raise unittest.SkipTest("platform has no sysconf name returning valid -1") + if __name__ == '__main__': unittest.main() diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java index 8b7e5eab41..62b6a03dfd 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java @@ -164,413 +164,414 @@ public final class NativePosixSupport extends PosixSupport { private static final Object CRYPT_LOCK = new Object(); abstract static class PosixNativeFunctionInvoker { - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT32}) abstract int init_constants(long out, int len); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT64, SINT32, SINT32, SINT32, SINT64}) + @DowncallSignature(returnType = SINT32) + abstract int get_errno(); + + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT64, SINT32, SINT32, SINT32, SINT64}) abstract long call_mmap(long length, int prot, int flags, int fd, long offset); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, SINT64}) abstract int call_munmap(long address, long length); - @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT64, SINT64, SINT64}) + @DowncallSignature(returnType = VOID, argumentTypes = {SINT64, SINT64, SINT64}) abstract void call_msync(long address, long offset, long length); - @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(returnType = VOID, argumentTypes = {SINT32, POINTER, SINT32}) abstract void call_strerror(int error, long buf, int buflen); - @DowncallSignature(captureCallState = true, returnType = SINT64) + @DowncallSignature(returnType = SINT64) abstract long call_getpid(); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_umask(int mask); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) abstract int call_openat(int dirFd, long pathname, int flags, int mode); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_close(int fd); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32, POINTER, SINT64}) + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32, POINTER, SINT64}) abstract long call_read(int fd, long buf, long count); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32, POINTER, SINT64}) + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32, POINTER, SINT64}) abstract long call_write(int fd, long buf, long count); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_dup(int fd); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32}) abstract int call_dup2(int oldfd, int newfd, int inheritable); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_pipe2(long pipefd); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER, SINT32, POINTER, SINT32, SINT64, SINT64, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER, SINT32, POINTER, SINT32, SINT64, SINT64, POINTER}) abstract int call_select(int nfds, long readfds, int readfdsLen, long writefds, int writefdsLen, long errfds, int errfdsLen, long timeoutSec, long timeoutUsec, long selected); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT64, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT64, SINT64}) abstract int call_poll(int fd, int writing, long timeoutSec, long timeoutUsec); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32, SINT64, SINT32}) + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32, SINT64, SINT32}) abstract long call_lseek(int fd, long offset, int whence); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT64}) abstract int call_ftruncate(int fd, long length); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT64}) abstract int call_truncate(long path, long length); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_fsync(int fd); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int call_flock(int fd, int operation); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, SINT32, SINT64, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, SINT32, SINT64, SINT64}) abstract int call_fcntl_lock(int fd, int blocking, int lockType, int whence, long start, long length); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER}) abstract int call_fstatat(int dirFd, long path, int followSymlinks, long out); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_fstat(int fd, long out); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER}) abstract int call_statvfs(long path, long out); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_fstatvfs(int fd, long out); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, POINTER, POINTER, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, POINTER, POINTER, POINTER, SINT32}) abstract int call_uname(long sysname, long nodename, long release, long version, long machine, int size); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) abstract int call_unlinkat(int dirFd, long pathname, int rmdir); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER, SINT32}) abstract int call_linkat(int oldDirFd, long oldPath, int newDirFd, long newPath, int flags); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT32, POINTER}) abstract int call_symlinkat(long target, int dirFd, long linkpath); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) abstract int call_mkdirat(int dirFd, long pathname, int mode); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT64}) abstract int call_getcwd(long buf, long size); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_chdir(long path); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_fchdir(int fd); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_isatty(int fd); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT64, argumentTypes = {POINTER}) abstract long call_opendir(long name); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32}) abstract long call_fdopendir(int fd); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64}) abstract int call_closedir(long dirp); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, POINTER, SINT64, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, POINTER, SINT64, POINTER}) abstract int call_readdir(long dirp, long nameBuf, long nameBufSize, long out); - @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT64}) + @DowncallSignature(returnType = VOID, argumentTypes = {SINT64}) abstract void call_rewinddir(long dirp); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER, SINT32}) abstract int call_utimensat(int dirFd, long path, long timespec, int followSymlinks); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_futimens(int fd, long timespec); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_futimes(int fd, long timeval); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER}) abstract int call_lutimes(long filename, long timeval); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER}) abstract int call_utimes(long filename, long timeval); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, POINTER}) abstract int call_renameat(int oldDirFd, long oldPath, int newDirFd, long newPath); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32}) abstract int call_faccessat(int dirFd, long path, int mode, int effectiveIds, int followSymlinks); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) abstract int call_fchmodat(int dirFd, long path, int mode, int followSymlinks); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int call_fchmod(int fd, int mode); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT64, SINT64, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT64, SINT64, SINT32}) abstract int call_fchownat(int dirfd, long pathname, long owner, long group, int followSymlinks); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT64, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT64, SINT64}) abstract int call_fchown(int fd, long owner, long group); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32, POINTER, POINTER, SINT64}) + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32, POINTER, POINTER, SINT64}) abstract long call_readlinkat(int dirFd, long path, long buf, long size); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int get_inheritable(int fd); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int set_inheritable(int fd, int inheritable); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int get_blocking(int fd); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int set_blocking(int fd, int blocking); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int get_terminal_size(int fd, long size); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_raise(int signal); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_alarm(int seconds); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_getitimer(int which, long currentValue); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_setitimer(int which, long newValue, long oldValue); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int signal_self(int signal); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, SINT32}) abstract int call_kill(long pid, int signal); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, SINT32}) abstract int call_killpg(long pgid, int signal); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT64, POINTER, SINT32}) + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT64, POINTER, SINT32}) abstract long call_waitpid(long pid, long status, int options); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wcoredump(int status); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wifcontinued(int status); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wifstopped(int status); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wifsignaled(int status); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wifexited(int status); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wexitstatus(int status); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wtermsig(int status); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32}) abstract int call_wstopsig(int status); - @DowncallSignature(captureCallState = true, returnType = SINT64) + @DowncallSignature(returnType = SINT64) abstract long call_getuid(); - @DowncallSignature(captureCallState = true, returnType = SINT64) + @DowncallSignature(returnType = SINT64) abstract long call_geteuid(); - @DowncallSignature(captureCallState = true, returnType = SINT64) + @DowncallSignature(returnType = SINT64) abstract long call_getgid(); - @DowncallSignature(captureCallState = true, returnType = SINT64) + @DowncallSignature(returnType = SINT64) abstract long call_getegid(); - @DowncallSignature(captureCallState = true, returnType = SINT64) + @DowncallSignature(returnType = SINT64) abstract long call_getppid(); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT64}) + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT64}) abstract long call_getpgid(long pid); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, SINT64}) abstract int call_setpgid(long pid, long pgid); - @DowncallSignature(captureCallState = true, returnType = SINT64) + @DowncallSignature(returnType = SINT64) abstract long call_getpgrp(); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT64}) + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT64}) abstract long call_getsid(long pid); - @DowncallSignature(captureCallState = true, returnType = SINT64) + @DowncallSignature(returnType = SINT64) abstract long call_setsid(); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, POINTER}) abstract int call_getgroups(long size, long out); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_getrusage(int who, long out); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_openpty(long outvars); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_ctermid(long buf); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32}) abstract int call_setenv(long name, long value, int overwrite); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_unsetenv(long name); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = { - POINTER, POINTER, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, - SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, POINTER, SINT64 - }) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, + SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, POINTER, SINT64}) abstract int fork_exec(long data, long offsets, int offsetsLen, int argsPos, int envPos, int cwdPos, int stdinRdFd, int stdinWrFd, int stdoutRdFd, int stdoutWrFd, int stderrRdFd, int stderrWrFd, int errPipeRdFd, int errPipeWrFd, int closeFds, int restoreSignals, int callSetsid, int pgidToSet, int allowVFork, long fdsToKeep, long fdsToKeepLen); - @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {POINTER, POINTER, SINT32}) + @DowncallSignature(returnType = VOID, argumentTypes = {POINTER, POINTER, SINT32}) abstract void call_execv(long data, long offsets, int offsetsLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_system(long pathname); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, POINTER, SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, POINTER, SINT32, POINTER}) abstract int call_getpwuid_r(long uid, long buffer, int bufferSize, long output); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, POINTER}) abstract int call_getpwname_r(long name, long buffer, int bufferSize, long output); - @DowncallSignature(captureCallState = true, returnType = VOID) + @DowncallSignature(returnType = VOID) abstract void call_setpwent(); - @DowncallSignature(captureCallState = true, returnType = VOID) + @DowncallSignature(returnType = VOID) abstract void call_endpwent(); - @DowncallSignature(captureCallState = true, returnType = POINTER, argumentTypes = {POINTER}) + @DowncallSignature(returnType = POINTER, argumentTypes = {POINTER}) abstract long call_getpwent(long bufferSize); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, POINTER}) abstract int get_getpwent_data(long p, long buffer, int bufferSize, long output); - @DowncallSignature(captureCallState = true, returnType = SINT64) + @DowncallSignature(returnType = SINT64) abstract long get_sysconf_getpw_r_size_max(); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32}) abstract int call_socket(int family, int type, int protocol); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_accept(int sockfd, long addr, long addrLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) abstract int call_bind(int sockfd, long addr, int addrLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32}) abstract int call_connect(int sockfd, long addr, int addrLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int call_listen(int sockfd, int backlog); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_getpeername(int sockfd, long addr, long addrLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_getsockname(int sockfd, long addr, long addrLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) abstract int call_send(int sockfd, long buf, int len, int flags); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32, POINTER, SINT32}) abstract int call_sendto(int sockfd, long buf, int offset, int len, int flags, long addr, int addrLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32}) abstract int call_recv(int sockfd, long buf, int len, int flags); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32, POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, SINT32, SINT32, SINT32, POINTER, POINTER}) abstract int call_recvfrom(int sockfd, long buf, int offset, int len, int flags, long srcAddr, long addrLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32}) abstract int call_shutdown(int sockfd, int how); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, POINTER, POINTER}) abstract int call_getsockopt(int sockfd, int level, int optname, long buf, long bufLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT32, SINT32, POINTER, SINT32}) abstract int call_setsockopt(int sockfd, int level, int optname, long buf, int bufLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_inet_addr(long src); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT64, argumentTypes = {POINTER}) abstract long call_inet_aton(long src); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER}) abstract int call_inet_ntoa(int src, long dst); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER}) abstract int call_inet_pton(int family, long src, long dst); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, POINTER, POINTER, SINT32}) abstract int call_inet_ntop(int family, long src, long dst, int dstSize); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT64}) abstract int call_gethostname(long buf, long bufLen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT32, POINTER, SINT32, POINTER, SINT32, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT32, POINTER, SINT32, POINTER, SINT32, SINT32}) abstract int call_getnameinfo(long addr, int addrLen, long hostBuf, int hostBufLen, long servBuf, int servBufLen, int flags); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, SINT32, SINT32, SINT32, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, SINT32, SINT32, SINT32, POINTER}) abstract int call_getaddrinfo(long node, long service, int family, int sockType, int protocol, int flags, long ptr); - @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT64}) + @DowncallSignature(returnType = VOID, argumentTypes = {SINT64}) abstract void call_freeaddrinfo(long ptr); - @DowncallSignature(captureCallState = true, returnType = VOID, argumentTypes = {SINT32, POINTER, SINT32}) + @DowncallSignature(returnType = VOID, argumentTypes = {SINT32, POINTER, SINT32}) abstract void call_gai_strerror(int error, long buf, int buflen); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT64, POINTER, POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT64, POINTER, POINTER, POINTER}) abstract int get_addrinfo_members(long ptr, long intData, long longData, long addr); - @DowncallSignature(captureCallState = true, returnType = POINTER, argumentTypes = {POINTER, SINT32, SINT32, SINT32}) + @DowncallSignature(returnType = POINTER, argumentTypes = {POINTER, SINT32, SINT32, SINT32}) abstract long call_sem_open(long name, int openFlags, int mode, int value); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_close(long handle); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_unlink(long name); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER}) abstract int call_sem_getvalue(long handle, long value); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_post(long handle); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_wait(long handle); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_sem_trywait(long handle); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {POINTER, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT64}) abstract int call_sem_timedwait(long handle, long deadlineNs); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT64, POINTER}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT64, POINTER}) abstract int call_ioctl_bytes(int fd, long request, long buffer); - @DowncallSignature(captureCallState = true, returnType = SINT32, argumentTypes = {SINT32, SINT64, SINT32}) + @DowncallSignature(returnType = SINT32, argumentTypes = {SINT32, SINT64, SINT32}) abstract int call_ioctl_int(int fd, long request, int arg); - @DowncallSignature(captureCallState = true, returnType = SINT64, argumentTypes = {SINT32}) + @DowncallSignature(returnType = SINT64, argumentTypes = {SINT32}) abstract long call_sysconf(int name); @TruffleBoundary @@ -595,7 +596,7 @@ static NativeLibrary loadNativeLibrary(PythonContext context) { } abstract static class CryptNativeFunctionInvoker { - @DowncallSignature(returnType = POINTER, argumentTypes = {POINTER, POINTER}) + @DowncallSignature(captureCallState = true, returnType = POINTER, argumentTypes = {POINTER, POINTER}) abstract long crypt(long word, long salt); @TruffleBoundary @@ -697,12 +698,8 @@ public long getpid() { } @ExportMessage - public int umask(int mask) throws PosixException { - int result = posixNativeFunctionInvoker.call_umask(mask); - if (result < 0) { - throw getErrnoAndThrowPosixException(); - } - return result; + public int umask(int mask) { + return posixNativeFunctionInvoker.call_umask(mask); } @ExportMessage @@ -980,11 +977,8 @@ public int[] getTerminalSize(int fd) throws PosixException { @ExportMessage public long sysconf(int name) throws PosixException { long result = posixNativeFunctionInvoker.call_sysconf(name); - if (result == -1) { - int errno = getErrno(); - if (errno != 0) { - throw newPosixException(errno); - } + if (result == Long.MIN_VALUE) { + throw getErrnoAndThrowPosixException(); } return result; } @@ -1249,23 +1243,22 @@ public Object readdir(Object dirStreamObj) throws PosixException { int result; do { result = posixNativeFunctionInvoker.call_readdir(dirStream, nativeName, DIRENT_NAME_BUF_LENGTH, nativeOut); - if (result != 0) { + if (result > 0) { NativeMemory.readByteArrayElements(nativeName, 0, name.data, 0, name.data.length); } - } while (result != 0 && name.data[0] == '.' && (name.data[1] == 0 || (name.data[1] == '.' && name.data[2] == 0))); - if (result != 0) { + } while (result > 0 && name.data[0] == '.' && (name.data[1] == 0 || (name.data[1] == '.' && name.data[2] == 0))); + if (result > 0) { NativeMemory.readLongArrayElements(nativeOut, 0, out, 0, out.length); return new DirEntry(name.withLength(findZero(name.data)), out[0], (int) out[1]); } + if (result < 0) { + throw getErrnoAndThrowPosixException(); + } } finally { NativeMemory.free(nativeOut); NativeMemory.free(nativeName); } - int errno = getErrno(); - if (errno == 0) { - return null; - } - throw newPosixException(errno); + return null; } @ExportMessage @@ -1515,8 +1508,8 @@ public void kill(long pid, int signal) throws PosixException { @ExportMessage public void raise(int signal) throws PosixException { int res = posixNativeFunctionInvoker.call_raise(signal); - if (res == -1) { - throw getErrnoAndThrowPosixException(); + if (res != 0) { + throw newPosixException(OSErrorEnum.EINVAL.getNumber()); } } @@ -1777,13 +1770,10 @@ public OpenPtyResult openpty() throws PosixException { @ExportMessage public TruffleString ctermid( @Bind Node inliningTarget, - @Shared("cString") @Cached NativeMemory.ZeroTerminatedUtf8ToTruffleStringNode zeroTerminatedUtf8ToTruffleStringNode) throws PosixException { + @Shared("cString") @Cached NativeMemory.ZeroTerminatedUtf8ToTruffleStringNode zeroTerminatedUtf8ToTruffleStringNode) { long nativeBuf = NativeMemory.mallocByteArray(L_ctermid.value); try { - int res = posixNativeFunctionInvoker.call_ctermid(nativeBuf); - if (res == -1) { - throw getErrnoAndThrowPosixException(); - } + posixNativeFunctionInvoker.call_ctermid(nativeBuf); // TODO PyUnicode_DecodeFSDefault return zeroTerminatedUtf8ToTruffleStringNode.execute(inliningTarget, nativeBuf); } finally { @@ -2554,7 +2544,7 @@ public TruffleString crypt(TruffleString word, TruffleString salt, // CPython doesn't handle the case of "invalid hash" return specially and neither do // we if (resultPtr == 0) { - throw getErrnoAndThrowPosixException(); + throw newPosixException(context.ensureNativeContext().getErrno()); } return zeroTerminatedUtf8ToTruffleStringNode.execute(raisingNode, resultPtr); } @@ -3399,6 +3389,6 @@ private static void log(Level level, String fmt, Object... args) { } private int getErrno() { - return context.ensureNativeContext().getErrno(); + return posixNativeFunctionInvoker.get_errno(); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index a771560e41..73a915caad 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -565,6 +565,7 @@ public void dispose(boolean clearNativeThreadLocalVarPointer, boolean markShutti NativeMemory.writePtr(nativeThreadLocalVarPointer, NULLPTR); } nativeThreadLocalVarPointer = NULLPTR; + } public Object getTraceFun() { @@ -658,6 +659,7 @@ public Object getNativeThreadLocalVarPointer() { public boolean isNativeThreadStateInitialized() { return nativeThreadLocalVarPointer != NULLPTR; } + } private static final class AtExitHook { diff --git a/graalpython/python-libposix/src/errno_capture.h b/graalpython/python-libposix/src/errno_capture.h new file mode 100644 index 0000000000..c1696a1957 --- /dev/null +++ b/graalpython/python-libposix/src/errno_capture.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2026, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef PYTHON_LIBPOSIX_ERRNO_CAPTURE_H +#define PYTHON_LIBPOSIX_ERRNO_CAPTURE_H + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define THREAD_LOCAL _Thread_local +#elif defined(_MSC_VER) + #define THREAD_LOCAL __declspec(thread) +#elif defined(__GNUC__) || defined(__clang__) + #define THREAD_LOCAL __thread +#else + #error "No thread-local storage support for this compiler" +#endif + +extern THREAD_LOCAL int errno_capture; + +static inline void capture_errno(void) { + errno_capture = errno; +} + +#define CAPTURE_ERRNO_AND_RETURN(indicator, expr) do { \ +__typeof__(expr) return_value = (expr); \ +if (return_value == (indicator)) { \ +capture_errno(); \ +} \ +return return_value; \ +} while (0) + +#endif //PYTHON_LIBPOSIX_ERRNO_CAPTURE_H diff --git a/graalpython/python-libposix/src/fork_exec.c b/graalpython/python-libposix/src/fork_exec.c index 476f72c987..397b4cd03d 100644 --- a/graalpython/python-libposix/src/fork_exec.c +++ b/graalpython/python-libposix/src/fork_exec.c @@ -21,6 +21,8 @@ #include #include +#include "errno_capture.h" + // These definitions emulate CPython's equivalents so that the copy&pasted code below works without too many changes #define HAVE_DIRFD 1 #define HAVE_SETSID 1 @@ -568,8 +570,7 @@ do_fork_exec(char *const exec_list[], * allowVFork - if nonzero, use vfork() instead of fork() where it is safe and supported * fdsToKeep, fdsToKeepLen - a sorted list of fds to keep open (the child clears their O_CLOEXEC) */ -int32_t fork_exec( - char *data, int64_t *offsets, int32_t offsetsLen, int32_t argsPos, int32_t envPos, int32_t cwdPos, +int32_t fork_exec(char *data, int64_t *offsets, int32_t offsetsLen, int32_t argsPos, int32_t envPos, int32_t cwdPos, int32_t stdinRdFd, int32_t stdinWrFd, int32_t stdoutRdFd, int32_t stdoutWrFd, int32_t stderrRdFd, int32_t stderrWrFd, @@ -579,8 +580,7 @@ int32_t fork_exec( int32_t callSetsid, int32_t pgidToSet, int32_t allowVFork, - int32_t *fdsToKeep, int64_t fdsToKeepLen - ) { + int32_t *fdsToKeep, int64_t fdsToKeepLen) { // We reuse the memory allocated for offsets to avoid the need to allocate and reliably free another array char **strings = (char **) offsets; @@ -603,6 +603,7 @@ int32_t fork_exec( int err = pthread_sigmask(SIG_BLOCK, &allSigs, &oldSigs); if (err) { errno = err; + capture_errno(); return -1; } oldSigmask = &oldSigs; @@ -631,5 +632,6 @@ int32_t fork_exec( } #endif + capture_errno(); return pid; } diff --git a/graalpython/python-libposix/src/posix.c b/graalpython/python-libposix/src/posix.c index 0420c5c119..2832edde43 100644 --- a/graalpython/python-libposix/src/posix.c +++ b/graalpython/python-libposix/src/posix.c @@ -77,6 +77,10 @@ #include #include +#include "errno_capture.h" + +THREAD_LOCAL int errno_capture = 0; + int32_t signal_self_segv(void); #ifdef __APPLE__ @@ -92,7 +96,7 @@ int32_t signal_self_segv(void); #include #endif -int64_t call_getpid() { +int64_t call_getpid(void) { return getpid(); } @@ -103,7 +107,8 @@ int32_t call_umask(int32_t mask) { int32_t get_inheritable(int32_t fd) { int flags = fcntl(fd, F_GETFD, 0); if (flags < 0) { - return -1; + capture_errno(); + return flags; } return !(flags & FD_CLOEXEC); } @@ -121,57 +126,57 @@ int32_t set_inheritable(int32_t fd, int32_t inheritable) { if (new_flags != res) { res = fcntl(fd, F_SETFD, new_flags); } + } else { + capture_errno(); } return res; } int32_t call_openat(int32_t dirFd, const char *pathname, int32_t flags, int32_t mode) { - return openat(dirFd, pathname, flags, mode); + CAPTURE_ERRNO_AND_RETURN(-1, openat(dirFd, pathname, flags, mode)); } int32_t call_close(int32_t fd) { - return close(fd); + CAPTURE_ERRNO_AND_RETURN(-1, close(fd)); } int64_t call_read(int32_t fd, void *buf, uint64_t count) { - errno = 0; - return read(fd, buf, count); + CAPTURE_ERRNO_AND_RETURN(-1, read(fd, buf, count)); } int64_t call_write(int32_t fd, void *buf, uint64_t count) { - errno = 0; - return write(fd, buf, count); + CAPTURE_ERRNO_AND_RETURN(-1, write(fd, buf, count)); } int32_t call_dup(int32_t fd) { - return fcntl(fd, F_DUPFD_CLOEXEC, 0); + CAPTURE_ERRNO_AND_RETURN(-1, fcntl(fd, F_DUPFD_CLOEXEC, 0)); } int32_t call_dup2(int32_t oldfd, int32_t newfd, int32_t inheritable) { #ifdef __gnu_linux__ if (!inheritable) { - return dup3(oldfd, newfd, O_CLOEXEC); + CAPTURE_ERRNO_AND_RETURN(-1, dup3(oldfd, newfd, O_CLOEXEC)); } #endif int res = dup2(oldfd, newfd); if (res < 0) { + capture_errno(); return res; } - if (!inheritable) { - if (set_inheritable(res, 0) < 0) { - close(res); - return -1; - } + if (!inheritable && set_inheritable(res, 0) < 0) { + close(res); + return -1; } return res; } int32_t call_pipe2(int32_t *pipefd) { #ifdef __gnu_linux__ - return pipe2(pipefd, O_CLOEXEC); + CAPTURE_ERRNO_AND_RETURN(-1, pipe2(pipefd, O_CLOEXEC)); #else int res = pipe(pipefd); if (res != 0) { + capture_errno(); return res; } if (set_inheritable(pipefd[0], 0) < 0 || set_inheritable(pipefd[1], 0) < 0) { @@ -222,7 +227,7 @@ int32_t call_select(int32_t nfds, int32_t* readfds, int32_t readfdsLen, fill_select_result(readfds, readfdsLen, &readfdsSet, selected, 0); fill_select_result(writefds, writefdsLen, &writefdsSet, selected, readfdsLen); fill_select_result(errfds, errfdsLen, &errfdsSet, selected, readfdsLen + writefdsLen); - return (int32_t) result; + CAPTURE_ERRNO_AND_RETURN(-1, (int32_t) result); } int32_t call_poll(int32_t fd, int32_t writing, int64_t timeoutSec, int64_t timeoutUsec) { @@ -244,37 +249,39 @@ int32_t call_poll(int32_t fd, int32_t writing, int64_t timeoutSec, int64_t timeo timeout_ms = -1; } else if (timeoutSec > INT_MAX / 1000) { errno = EINVAL; + capture_errno(); return -1; } else { int64_t timeout_ms_64 = timeoutSec * 1000 + timeoutUsec / 1000; if (timeout_ms_64 > INT_MAX) { errno = EINVAL; + capture_errno(); return -1; } timeout_ms = (int)timeout_ms_64; } - return poll(&pollfd, 1, timeout_ms); + CAPTURE_ERRNO_AND_RETURN(-1, poll(&pollfd, 1, timeout_ms)); #endif } int64_t call_lseek(int32_t fd, int64_t offset, int32_t whence) { - return lseek(fd, offset, whence); + CAPTURE_ERRNO_AND_RETURN(-1, lseek(fd, offset, whence)); } int32_t call_ftruncate(int32_t fd, int64_t length) { - return ftruncate(fd, length); + CAPTURE_ERRNO_AND_RETURN(-1, ftruncate(fd, length)); } int32_t call_truncate(const char* path, int64_t length) { - return truncate(path, length); + CAPTURE_ERRNO_AND_RETURN(-1, truncate(path, length)); } int32_t call_fsync(int32_t fd) { - return fsync(fd); + CAPTURE_ERRNO_AND_RETURN(-1, fsync(fd)); } int32_t call_flock(int32_t fd, int32_t operation) { - return flock(fd, operation); + CAPTURE_ERRNO_AND_RETURN(-1, flock(fd, operation)); } int32_t call_fcntl_lock(int32_t fd, int32_t blocking, int32_t lockType, int32_t whence, int64_t start, int64_t length) { @@ -283,12 +290,13 @@ int32_t call_fcntl_lock(int32_t fd, int32_t blocking, int32_t lockType, int32_t l.l_whence = whence; l.l_start = start; l.l_len = length; - return fcntl(fd, blocking ? F_SETLKW : F_SETLK, &l); + CAPTURE_ERRNO_AND_RETURN(-1, fcntl(fd, blocking ? F_SETLKW : F_SETLK, &l)); } int32_t get_blocking(int32_t fd) { int flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { + if (flags == -1) { + capture_errno(); return -1; } return !(flags & O_NONBLOCK); @@ -305,7 +313,7 @@ int32_t set_blocking(int32_t fd, int32_t blocking) { } res = fcntl(fd, F_SETFL, flags); } - return res; + CAPTURE_ERRNO_AND_RETURN(-1, res); } int32_t get_terminal_size(int32_t fd, int32_t *size) { @@ -314,6 +322,8 @@ int32_t get_terminal_size(int32_t fd, int32_t *size) { if (res == 0) { size[0] = w.ws_col; size[1] = w.ws_row; + } else { + capture_errno(); } return res; } @@ -349,6 +359,8 @@ int32_t call_fstatat(int32_t dirFd, const char *path, int32_t followSymlinks, in int result = fstatat(dirFd, path, &st, followSymlinks ? 0 : AT_SYMLINK_NOFOLLOW); if (result == 0) { stat_struct_to_longs(&st, out); + } else { + capture_errno(); } return result; } @@ -358,6 +370,8 @@ int32_t call_fstat(int32_t fd, int64_t *out) { int result = fstat(fd, &st); if (result == 0) { stat_struct_to_longs(&st, out); + } else { + capture_errno(); } return result; } @@ -382,6 +396,8 @@ int32_t call_statvfs(const char *path, int64_t *out) { int result = statvfs(path, &st); if (result == 0) { statvfs_struct_to_longs(&st, out); + } else { + capture_errno(); } return result; } @@ -391,6 +407,8 @@ int32_t call_fstatvfs(int32_t fd, int64_t *out) { int result = fstatvfs(fd, &st); if (result == 0) { statvfs_struct_to_longs(&st, out); + } else { + capture_errno(); } return result; } @@ -404,44 +422,46 @@ int32_t call_uname(char *sysname, char *nodename, char *release, char *version, snprintf(release, size, "%s", buf.release); snprintf(version, size, "%s", buf.version); snprintf(machine, size, "%s", buf.machine); + } else { + capture_errno(); } return result; } int32_t call_unlinkat(int32_t dirFd, const char *pathname, int32_t rmdir) { - return unlinkat(dirFd, pathname, rmdir ? AT_REMOVEDIR : 0); + CAPTURE_ERRNO_AND_RETURN(-1, unlinkat(dirFd, pathname, rmdir ? AT_REMOVEDIR : 0)); } int32_t call_linkat(int32_t oldDirFd, const char *oldPath, int32_t newDirFd, const char *newPath, int32_t flags) { - return linkat(oldDirFd, oldPath, newDirFd, newPath, flags); + CAPTURE_ERRNO_AND_RETURN(-1, linkat(oldDirFd, oldPath, newDirFd, newPath, flags)); } int32_t call_symlinkat(const char *target, int32_t dirFd, const char *linkpath) { - return symlinkat(target, dirFd, linkpath); + CAPTURE_ERRNO_AND_RETURN(-1, symlinkat(target, dirFd, linkpath)); } int32_t call_mkdirat(int32_t dirFd, const char *pathname, int32_t mode) { - return mkdirat(dirFd, pathname, mode); + CAPTURE_ERRNO_AND_RETURN(-1, mkdirat(dirFd, pathname, mode)); } int32_t call_getcwd(char *buf, uint64_t size) { - return getcwd(buf, size) == NULL ? -1 : 0; + CAPTURE_ERRNO_AND_RETURN(-1, getcwd(buf, size) == NULL ? -1 : 0); } int32_t call_chdir(const char *path) { - return chdir(path); + CAPTURE_ERRNO_AND_RETURN(-1, chdir(path)); } int32_t call_fchdir(int32_t fd) { - return fchdir(fd); + CAPTURE_ERRNO_AND_RETURN(-1, fchdir(fd)); } int32_t call_fchown(int32_t fd, int64_t owner, int64_t group) { - return fchown(fd, owner, group); + CAPTURE_ERRNO_AND_RETURN(-1, fchown(fd, owner, group)); } int32_t call_fchownat(int32_t dirfd, const char *pathname, int64_t owner, int64_t group, int32_t followSymlinks) { - return fchownat(dirfd, pathname, owner, group, followSymlinks ? 0 : AT_SYMLINK_NOFOLLOW); + CAPTURE_ERRNO_AND_RETURN(-1, fchownat(dirfd, pathname, owner, group, followSymlinks ? 0 : AT_SYMLINK_NOFOLLOW)); } int32_t call_isatty(int32_t fd) { @@ -449,15 +469,15 @@ int32_t call_isatty(int32_t fd) { } intptr_t call_opendir(const char *name) { - return (intptr_t) opendir(name); + CAPTURE_ERRNO_AND_RETURN(0, (intptr_t) opendir(name)); } intptr_t call_fdopendir(int32_t fd) { - return (intptr_t) fdopendir(fd); + CAPTURE_ERRNO_AND_RETURN(0, (intptr_t) fdopendir(fd)); } int32_t call_closedir(intptr_t dirp) { - return closedir((DIR *) dirp); + CAPTURE_ERRNO_AND_RETURN(-1, closedir((DIR *) dirp)); } int32_t call_readdir(intptr_t dirp, char *nameBuf, uint64_t nameBufSize, int64_t *out) { @@ -469,6 +489,10 @@ int32_t call_readdir(intptr_t dirp, char *nameBuf, uint64_t nameBufSize, int64_t out[1] = dirEntry->d_type; return 1; } + if (errno != 0) { + capture_errno(); + return -1; + } return 0; } @@ -479,72 +503,72 @@ void call_rewinddir(intptr_t dirp) { #ifdef __gnu_linux__ int32_t call_utimensat(int32_t dirFd, const char *path, int64_t *timespec, int32_t followSymlinks) { if (!timespec) { - return utimensat(dirFd, path, NULL, followSymlinks ? 0 : AT_SYMLINK_NOFOLLOW); + CAPTURE_ERRNO_AND_RETURN(-1, utimensat(dirFd, path, NULL, followSymlinks ? 0 : AT_SYMLINK_NOFOLLOW)); } else { struct timespec times[2]; times[0].tv_sec = timespec[0]; times[0].tv_nsec = timespec[1]; times[1].tv_sec = timespec[2]; times[1].tv_nsec = timespec[3]; - return utimensat(dirFd, path, times, followSymlinks ? 0 : AT_SYMLINK_NOFOLLOW); + CAPTURE_ERRNO_AND_RETURN(-1, utimensat(dirFd, path, times, followSymlinks ? 0 : AT_SYMLINK_NOFOLLOW)); } } int32_t call_futimens(int32_t fd, int64_t *timespec) { if (!timespec) { - return futimens(fd, NULL); + CAPTURE_ERRNO_AND_RETURN(-1, futimens(fd, NULL)); } else { struct timespec times[2]; times[0].tv_sec = timespec[0]; times[0].tv_nsec = timespec[1]; times[1].tv_sec = timespec[2]; times[1].tv_nsec = timespec[3]; - return futimens(fd, times); + CAPTURE_ERRNO_AND_RETURN(-1, futimens(fd, times)); } } #endif int32_t call_futimes(int32_t fd, int64_t *timeval) { if (!timeval) { - return futimes(fd, NULL); + CAPTURE_ERRNO_AND_RETURN(-1, futimes(fd, NULL)); } else { struct timeval times[2]; times[0].tv_sec = timeval[0]; times[0].tv_usec = timeval[1]; times[1].tv_sec = timeval[2]; times[1].tv_usec = timeval[3]; - return futimes(fd, times); + CAPTURE_ERRNO_AND_RETURN(-1, futimes(fd, times)); } } int32_t call_lutimes(const char *filename, int64_t *timeval) { if (!timeval) { - return lutimes(filename, NULL); + CAPTURE_ERRNO_AND_RETURN(-1, lutimes(filename, NULL)); } else { struct timeval times[2]; times[0].tv_sec = timeval[0]; times[0].tv_usec = timeval[1]; times[1].tv_sec = timeval[2]; times[1].tv_usec = timeval[3]; - return lutimes(filename, times); + CAPTURE_ERRNO_AND_RETURN(-1, lutimes(filename, times)); } } int32_t call_utimes(const char *filename, int64_t *timeval) { if (!timeval) { - return utimes(filename, NULL); + CAPTURE_ERRNO_AND_RETURN(-1, utimes(filename, NULL)); } else { struct timeval times[2]; times[0].tv_sec = timeval[0]; times[0].tv_usec = timeval[1]; times[1].tv_sec = timeval[2]; times[1].tv_usec = timeval[3]; - return utimes(filename, times); + CAPTURE_ERRNO_AND_RETURN(-1, utimes(filename, times)); } } int32_t call_renameat(int32_t oldDirFd, const char *oldPath, int32_t newDirFd, const char *newPath) { - return renameat(oldDirFd, oldPath, newDirFd, newPath); + CAPTURE_ERRNO_AND_RETURN(-1, renameat(oldDirFd, oldPath, newDirFd, newPath)); } int32_t call_faccessat(int32_t dirFd, const char *path, int32_t mode, int32_t effectiveIds, int32_t followSymlinks) { @@ -555,23 +579,23 @@ int32_t call_faccessat(int32_t dirFd, const char *path, int32_t mode, int32_t ef if (effectiveIds) { flags |= AT_EACCESS; } - return faccessat(dirFd, path, mode, flags); + CAPTURE_ERRNO_AND_RETURN(-1, faccessat(dirFd, path, mode, flags)); } int32_t call_fchmodat(int32_t dirFd, const char *path, int32_t mode, int32_t followSymlinks) { - return fchmodat(dirFd, path, mode, followSymlinks ? 0 : AT_SYMLINK_NOFOLLOW); + CAPTURE_ERRNO_AND_RETURN(-1, fchmodat(dirFd, path, mode, followSymlinks ? 0 : AT_SYMLINK_NOFOLLOW)); } int32_t call_fchmod(int32_t fd, int32_t mode) { - return fchmod(fd, mode); + CAPTURE_ERRNO_AND_RETURN(-1, fchmod(fd, mode)); } int64_t call_readlinkat(int32_t dirFd, const char *path, char *buf, uint64_t size) { - return readlinkat(dirFd, path, buf, size); + CAPTURE_ERRNO_AND_RETURN(-1, readlinkat(dirFd, path, buf, size)); } int64_t call_waitpid(int64_t pid, int32_t *status, int32_t options) { - return waitpid(pid, status, options); + CAPTURE_ERRNO_AND_RETURN(-1, waitpid(pid, status, options)); } int32_t call_wcoredump(int32_t status) { @@ -607,7 +631,7 @@ int32_t call_wstopsig(int32_t status) { } int32_t call_kill(int64_t pid, int32_t signal) { - return kill(pid, signal); + CAPTURE_ERRNO_AND_RETURN(-1, kill(pid, signal)); } int32_t call_raise(int32_t signal) { @@ -637,6 +661,8 @@ int32_t call_getitimer(int32_t which, int64_t *current_value) { int32_t result = getitimer(which, ¤t); if (result == 0) { itimerval_to_long_array(¤t, current_value); + } else { + capture_errno(); } return result; } @@ -648,6 +674,8 @@ int32_t call_setitimer(int32_t which, int64_t *new_value, int64_t *old_value) { int32_t result = setitimer(which, &new_timer, &old_timer); if (result == 0) { itimerval_to_long_array(&old_timer, old_value); + } else { + capture_errno(); } return result; } @@ -661,53 +689,54 @@ int32_t signal_self(int32_t signal) { return signal_self_segv(); default: errno = EINVAL; + capture_errno(); return -1; } _exit(128 + signal); } int32_t call_killpg(int64_t pgid, int32_t signal) { - return killpg(pgid, signal); + CAPTURE_ERRNO_AND_RETURN(-1, killpg(pgid, signal)); } -int64_t call_getuid() { +int64_t call_getuid(void) { return getuid(); } -int64_t call_geteuid() { +int64_t call_geteuid(void) { return geteuid(); } -int64_t call_getgid() { +int64_t call_getgid(void) { return getgid(); } -int64_t call_getegid() { +int64_t call_getegid(void) { return getegid(); } -int64_t call_getppid() { +int64_t call_getppid(void) { return getppid(); } int64_t call_getpgid(int64_t pid) { - return getpgid(pid); + CAPTURE_ERRNO_AND_RETURN(-1, getpgid(pid)); } int32_t call_setpgid(int64_t pid, int64_t pgid) { - return setpgid(pid, pgid); + CAPTURE_ERRNO_AND_RETURN(-1, setpgid(pid, pgid)); } -int64_t call_getpgrp() { +int64_t call_getpgrp(void) { return getpgrp(); } int64_t call_getsid(int64_t pid) { - return getsid(pid); + CAPTURE_ERRNO_AND_RETURN(-1, getsid(pid)); } int64_t call_setsid() { - return setsid(); + CAPTURE_ERRNO_AND_RETURN(-1, setsid()); } int32_t call_getgroups(int64_t size, int64_t* out) { @@ -722,9 +751,9 @@ int32_t call_getgroups(int64_t size, int64_t* out) { out[i] = tmp[i]; } free(tmp); - return res; + CAPTURE_ERRNO_AND_RETURN(-1, res); } else { - return getgroups(size, NULL); + CAPTURE_ERRNO_AND_RETURN(-1, getgroups(size, NULL)); } } @@ -732,8 +761,8 @@ int32_t call_getrusage(int32_t who, uint64_t* out) { #ifndef _WIN32 struct rusage ru; int result = getrusage(who, &ru); - if (result != 0) { - return result; + if (result == -1) { + CAPTURE_ERRNO_AND_RETURN(-1, result); } int offset = 0; // POSIX prescribes only ru_utime and ru_stime members, macOS and Linux @@ -759,16 +788,17 @@ int32_t call_getrusage(int32_t who, uint64_t* out) { COPYLONG(ru.ru_nsignals); COPYLONG(ru.ru_nvcsw); COPYLONG(ru.ru_nivcsw); - return 0; + CAPTURE_ERRNO_AND_RETURN(-1, 0); # undef COPYLONG # undef COPYDOUBLE #else - return -1; + errno = ENOSYS; + capture_errno(); #endif } int32_t call_openpty(int32_t *outvars) { - return openpty(outvars, outvars + 1, NULL, NULL, NULL); + CAPTURE_ERRNO_AND_RETURN(-1, openpty(outvars, outvars + 1, NULL, NULL, NULL)); } int32_t call_ctermid(char *buf) { @@ -776,11 +806,11 @@ int32_t call_ctermid(char *buf) { } int32_t call_setenv(char *name, char *value, int overwrite) { - return setenv(name, value, overwrite); + CAPTURE_ERRNO_AND_RETURN(-1, setenv(name, value, overwrite)); } int32_t call_unsetenv(char *name) { - return unsetenv(name); + CAPTURE_ERRNO_AND_RETURN(-1, unsetenv(name)); } // See comment in NativePosixSupport.execv() for the description of arguments @@ -794,6 +824,7 @@ void call_execv(char *data, int64_t *offsets, int32_t offsetsLen) { char *pathname = strings[0]; char **argv = strings + 1; execv(pathname, argv); + capture_errno(); } int32_t call_system(const char *pathname) { @@ -802,11 +833,15 @@ int32_t call_system(const char *pathname) { int64_t call_mmap(int64_t length, int32_t prot, int32_t flags, int32_t fd, int64_t offset) { void *result = mmap(NULL, length, prot, flags, fd, offset); - return result == MAP_FAILED ? 0 : (int64_t) result; + if (result == MAP_FAILED) { + capture_errno(); + return 0; + } + return (int64_t) result; } int32_t call_munmap(int64_t address, int64_t length) { - return munmap((void *) address, length); + CAPTURE_ERRNO_AND_RETURN(-1, munmap((void *) address, length)); } void call_msync(int64_t address, int64_t offset, int64_t length) { @@ -816,7 +851,7 @@ void call_msync(int64_t address, int64_t offset, int64_t length) { } int32_t call_socket(int32_t family, int32_t type, int32_t protocol) { - return socket(family, type, protocol); + CAPTURE_ERRNO_AND_RETURN(-1, socket(family, type, protocol)); } // On Java side, socket addresses are stored in a Java byte[] (here represented by a int8_t *). @@ -833,23 +868,23 @@ int32_t call_accept(int32_t sockfd, int8_t *addr, int32_t *addr_len) { *addr_len = (int32_t)l; // ...so this unsigned->signed conversion is well defined memcpy(addr, &sa, l); } - return res; + CAPTURE_ERRNO_AND_RETURN(-1, res); } int32_t call_bind(int32_t sockfd, int8_t *addr, int32_t addr_len) { struct sockaddr_storage sa; memcpy(&sa, addr, addr_len); - return bind(sockfd, (struct sockaddr *) &sa, addr_len); + CAPTURE_ERRNO_AND_RETURN(-1, bind(sockfd, (struct sockaddr *) &sa, addr_len)); } int32_t call_connect(int32_t sockfd, int8_t *addr, int32_t addr_len) { struct sockaddr_storage sa; memcpy(&sa, addr, addr_len); - return connect(sockfd, (struct sockaddr *) &sa, addr_len); + CAPTURE_ERRNO_AND_RETURN(-1, connect(sockfd, (struct sockaddr *) &sa, addr_len)); } int32_t call_listen(int32_t sockfd, int32_t backlog) { - return listen(sockfd, backlog); + CAPTURE_ERRNO_AND_RETURN(-1, listen(sockfd, backlog)); } int32_t call_getpeername(int32_t sockfd, int8_t *addr, int32_t *addr_len) { @@ -860,6 +895,8 @@ int32_t call_getpeername(int32_t sockfd, int8_t *addr, int32_t *addr_len) { assert(l <= sizeof(sockaddr_storage)); // l is small enough to be representable by int32_t... *addr_len = (int32_t)l; // ...so this unsigned->signed conversion is well defined memcpy(addr, &sa, l); + } else { + capture_errno(); } return res; } @@ -872,43 +909,46 @@ int32_t call_getsockname(int32_t sockfd, int8_t *addr, int32_t *addr_len) { assert(l <= sizeof(sockaddr_storage)); // l is small enough to be representable by int32_t... *addr_len = (int32_t)l; // ...so this unsigned->signed conversion is well defined memcpy(addr, &sa, l); + } else { + capture_errno(); } return res; } //TODO len should be size_t, retval should be ssize_t int32_t call_send(int32_t sockfd, void *buf, int32_t len, int32_t flags) { - errno = 0; - return send(sockfd, buf, len, flags); + ssize_t res = send(sockfd, buf, len, flags); + assert (res == (int32_t) res); + CAPTURE_ERRNO_AND_RETURN(-1, res); } int32_t call_sendto(int32_t sockfd, void *buf, int32_t offset, int32_t len, int32_t flags, int8_t *addr, int32_t addr_len) { struct sockaddr_storage sa; memcpy(&sa, addr, addr_len); - errno = 0; - return sendto(sockfd, buf + offset, len, flags, (struct sockaddr *) &sa, addr_len); + CAPTURE_ERRNO_AND_RETURN(-1, sendto(sockfd, buf + offset, len, flags, (struct sockaddr *) &sa, addr_len)); } int32_t call_recv(int32_t sockfd, void *buf, int32_t len, int32_t flags) { - errno = 0; - return recv(sockfd, buf, len, flags); + CAPTURE_ERRNO_AND_RETURN(-1, recv(sockfd, buf, len, flags)); } int32_t call_recvfrom(int32_t sockfd, void *buf, int32_t offset, int32_t len, int32_t flags, int8_t *src_addr, int32_t *addr_len) { struct sockaddr_storage sa; socklen_t l = sizeof(sa); - errno = 0; - int res = recvfrom(sockfd, buf + offset, len, flags, (struct sockaddr *) &sa, &l); + ssize_t res = recvfrom(sockfd, buf + offset, len, flags, (struct sockaddr *) &sa, &l); if (res != -1) { assert(l <= sizeof(sockaddr_storage)); // l is small enough to be representable by int32_t... *addr_len = (int32_t)l; // ...so this unsigned->signed conversion is well defined memcpy(src_addr, &sa, l); + } else { + capture_errno(); } - return res; + assert (res == (int32_t) res); + return (int32_t) res; } int32_t call_shutdown(int32_t sockfd, int32_t how) { - return shutdown(sockfd, how); + CAPTURE_ERRNO_AND_RETURN(-1, shutdown(sockfd, how)); } #define MAX_SOCKOPT_LEN 1024 @@ -927,12 +967,15 @@ int32_t call_getsockopt(int32_t sockfd, int32_t level, int32_t optname, void *bu if (len > sizeof(alignedBuf)) { // If this ever happens, we can increase MAX_SOCKOPT_LEN or use malloc. errno = ENOMEM; + capture_errno(); return -1; } int res = getsockopt(sockfd, level, optname, alignedBuf, &len); if (res == 0) { *bufLen = len; memcpy(buf, alignedBuf, len); + } else { + capture_errno(); } return res; } @@ -942,10 +985,11 @@ int32_t call_setsockopt(int32_t sockfd, int32_t level, int32_t optname, void *bu char alignedBuf[MAX_SOCKOPT_LEN] __attribute__ ((aligned)); if (bufLen > sizeof(alignedBuf)) { errno = ENOMEM; + capture_errno(); return -1; } memcpy(alignedBuf, buf, bufLen); - return setsockopt(sockfd, level, optname, alignedBuf, bufLen); + CAPTURE_ERRNO_AND_RETURN(-1, setsockopt(sockfd, level, optname, alignedBuf, bufLen)); } int32_t call_inet_addr(const char *src) { @@ -972,16 +1016,16 @@ int32_t call_inet_ntoa(int32_t src, char *dst) { } int32_t call_inet_pton(int32_t family, const char *src, void *dst) { - return inet_pton(family, src, dst); + CAPTURE_ERRNO_AND_RETURN(-1, inet_pton(family, src, dst)); } int32_t call_inet_ntop(int32_t family, void *src, char *dst, int32_t dstSize) { const char *r = inet_ntop(family, src, dst, dstSize); - return r == NULL ? -1 : 0; + CAPTURE_ERRNO_AND_RETURN(-1, r == NULL ? -1 : 0); } int32_t call_gethostname(char *buf, int64_t bufLen) { - return gethostname(buf, bufLen); + CAPTURE_ERRNO_AND_RETURN(-1, gethostname(buf, bufLen)); } int32_t call_getnameinfo(int8_t *addr, int32_t addr_len, char *hostBuf, int32_t hostBufLen, char *servBuf, int32_t servBufLen, int32_t flags) { @@ -1041,50 +1085,54 @@ int32_t get_addrinfo_members(int64_t ptr, int32_t *intData, int64_t *longData, i sem_t* call_sem_open(const char *name, int32_t openFlags, int32_t mode, int32_t value) { sem_t* result = sem_open(name, openFlags, mode, value); - if (result == (sem_t*)SEM_FAILED) { - return NULL; + if (result == SEM_FAILED) { + capture_errno(); } return result; } int32_t call_sem_close(sem_t* handle) { - return sem_close(handle); + CAPTURE_ERRNO_AND_RETURN(-1, sem_close(handle)); } int32_t call_sem_unlink(const char *name) { - return sem_unlink(name); + CAPTURE_ERRNO_AND_RETURN(-1, sem_unlink(name)); } #ifdef __linux__ int32_t call_sem_getvalue(sem_t* handle, int32_t *value) { int valueInt; int res = sem_getvalue(handle, &valueInt); - *value = valueInt; + if (res == 0) { + *value = valueInt; + } else { + capture_errno(); + } return res; } #endif int32_t call_sem_post(sem_t* handle) { - return sem_post(handle); + CAPTURE_ERRNO_AND_RETURN(-1, sem_post(handle)); } int32_t call_sem_wait(sem_t* handle) { - return sem_wait(handle); + CAPTURE_ERRNO_AND_RETURN(-1, sem_wait(handle)); } int32_t call_sem_trywait(sem_t* handle) { - return sem_trywait(handle); + CAPTURE_ERRNO_AND_RETURN(-1, sem_trywait(handle)); } #ifdef __linux__ int32_t call_sem_timedwait(sem_t* handle, int64_t deadlineNs) { const int64_t nsInSec = 1000 * 1000 * 1000; struct timespec deadline = {deadlineNs / nsInSec, deadlineNs % nsInSec}; - return sem_timedwait(handle, &deadline); + CAPTURE_ERRNO_AND_RETURN(-1, sem_timedwait(handle, &deadline)); } #endif -int32_t get_sysconf_getpw_r_size_max() { +int64_t get_sysconf_getpw_r_size_max(void) { return sysconf(_SC_GETPW_R_SIZE_MAX); } @@ -1135,11 +1183,11 @@ int32_t call_getpwname_r(const char *name, char *buffer, int32_t bufferSize, uin // Following 3 functions are not thread safe: -void call_setpwent() { +void call_setpwent(void) { setpwent(); } -void call_endpwent() { +void call_endpwent(void) { endpwent(); } @@ -1149,6 +1197,8 @@ struct passwd *call_getpwent(int64_t *bufferSize) { // the +3 is for terminating '\0' *bufferSize = strlen(p->pw_name) + strlen(p->pw_dir) + strlen(p->pw_shell) + 3; } + // always capture errno because NULL result may also be a valid result + capture_errno(); return p; } @@ -1176,16 +1226,26 @@ int32_t get_getpwent_data(struct passwd *p, char *buffer, int32_t bufferSize, ui } int32_t call_ioctl_bytes(int32_t fd, uint64_t request, char* buffer) { - return ioctl(fd, request, buffer); + CAPTURE_ERRNO_AND_RETURN(-1, ioctl(fd, request, buffer)); } int32_t call_ioctl_int(int32_t fd, uint64_t request, int32_t arg) { - return ioctl(fd, request, (int)arg); + CAPTURE_ERRNO_AND_RETURN(-1, ioctl(fd, request, (int)arg)); } int64_t call_sysconf(int32_t name) { errno = 0; - return sysconf(name); + int64_t result = sysconf(name); + if (result == -1 && errno != 0) { + capture_errno(); + // Private sentinel: sysconf itself may return -1 without an error. + return INT64_MIN; + } + return result; +} + +int32_t get_errno() { + return errno_capture; } #ifdef _WIN32 From 70fd5a706f0dced67138a7c18f2b0dd41e88590b Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 25 Jun 2026 12:12:52 +0200 Subject: [PATCH 4/7] Unify native downcall handle creation --- .../processor/CApiBuiltinsProcessor.java | 49 ++++------------ .../GenerateNativeDowncallsProcessor.java | 2 +- .../NativeDowncallMethodHandleGenerator.java | 58 +++++++++---------- .../nodes/arrow/ArrowReleaseCallback.java | 7 ++- .../nativeaccess/NativeAccessSupport.java | 37 +----------- .../NativeAccessSupportJdk21.java | 17 +++++- .../runtime/nativeaccess/NativeContext.java | 18 +++--- 7 files changed, 71 insertions(+), 117 deletions(-) diff --git a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/CApiBuiltinsProcessor.java b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/CApiBuiltinsProcessor.java index 6fd1c15288..9ab98a9bd6 100644 --- a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/CApiBuiltinsProcessor.java +++ b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/CApiBuiltinsProcessor.java @@ -1411,8 +1411,8 @@ private void generateExternalFunctionInvoker(List options = new ArrayList<>();"); lines.add(" if (critical) {"); lines.add(" options.add(Linker.Option.critical(false));"); @@ -1709,33 +1715,6 @@ private void generateNativeAccessSupport(Element[] origins) throws IOException { lines.add(" return resType == NativeSimpleType.VOID ? FunctionDescriptor.ofVoid(argLayouts) : FunctionDescriptor.of(asLayout(resType), argLayouts);"); lines.add(" }"); lines.add(""); - lines.add(" private static FunctionDescriptor createFunctionDescriptor(MethodType methodType, int firstNativeArg) {"); - lines.add(" Class[] parameterTypes = methodType.parameterArray();"); - lines.add(" MemoryLayout[] argLayouts = new MemoryLayout[parameterTypes.length - firstNativeArg];"); - lines.add(" for (int i = firstNativeArg; i < parameterTypes.length; i++) {"); - lines.add(" argLayouts[i - firstNativeArg] = asLayout(parameterTypes[i]);"); - lines.add(" }"); - lines.add(" Class returnType = methodType.returnType();"); - lines.add(" return returnType == void.class ? FunctionDescriptor.ofVoid(argLayouts) : FunctionDescriptor.of(asLayout(returnType), argLayouts);"); - lines.add(" }"); - lines.add(""); - lines.add(" private static MemoryLayout asLayout(Class type) {"); - lines.add(" if (type == byte.class) {"); - lines.add(" return ValueLayout.JAVA_BYTE;"); - lines.add(" } else if (type == short.class) {"); - lines.add(" return ValueLayout.JAVA_SHORT;"); - lines.add(" } else if (type == int.class) {"); - lines.add(" return ValueLayout.JAVA_INT;"); - lines.add(" } else if (type == long.class) {"); - lines.add(" return ValueLayout.JAVA_LONG;"); - lines.add(" } else if (type == float.class) {"); - lines.add(" return ValueLayout.JAVA_FLOAT;"); - lines.add(" } else if (type == double.class) {"); - lines.add(" return ValueLayout.JAVA_DOUBLE;"); - lines.add(" }"); - lines.add(" throw shouldNotReachHere(\"Unsupported layout carrier: \" + type);"); - lines.add(" }"); - lines.add(""); lines.add(" private static MemoryLayout asLayout(NativeSimpleType type) {"); lines.add(" return switch (type) {"); lines.add(" case VOID -> throw shouldNotReachHere(\"VOID has no layout\");"); @@ -1765,7 +1744,6 @@ private void generateDummyNativeAccessSupport(Element[] origins) throws IOExcept lines.add("package " + NATIVE_ACCESS_PACKAGE + ";"); lines.add(""); lines.add("import java.lang.invoke.MethodHandle;"); - lines.add("import java.lang.invoke.MethodType;"); lines.add(""); lines.add("import " + NativeSimpleType.class.getCanonicalName() + ";"); lines.add(""); @@ -1791,17 +1769,12 @@ private void generateDummyNativeAccessSupport(Element[] origins) throws IOExcept lines.add(" }"); lines.add(""); lines.add(" @Override"); - lines.add(" protected MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical, boolean captureCallState) {"); - lines.add(" throw unsupported();"); - lines.add(" }"); - lines.add(""); - lines.add(" @Override"); - lines.add(" protected Object createCapturedCallStateImpl() {"); + lines.add(" protected MethodHandle createDowncallHandleImpl(boolean critical, boolean captureCallState, NativeSimpleType resType, NativeSimpleType[] argTypes) {"); lines.add(" throw unsupported();"); lines.add(" }"); lines.add(""); lines.add(" @Override"); - lines.add(" protected Object getCapturedCallStateSegmentImpl(Object state) {"); + lines.add(" protected Object createCapturedCallStateImpl(Object arena) {"); lines.add(" throw unsupported();"); lines.add(" }"); lines.add(""); diff --git a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java index e1247cf456..ac236e6a7f 100644 --- a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java +++ b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java @@ -143,10 +143,10 @@ private void generateInvoker(TypeElement invokerElement) throws IOException, Pro lines.add(""); lines.add("import java.lang.foreign.MemorySegment;"); lines.add("import java.lang.invoke.MethodHandle;"); - lines.add("import java.lang.invoke.MethodType;"); lines.add("import java.util.concurrent.atomic.AtomicLongArray;"); lines.add("import java.util.List;"); lines.add(""); + lines.add("import com.oracle.graal.python.annotations.NativeSimpleType;"); lines.add("import com.oracle.graal.python.runtime.nativeaccess.NativeAccessSupport;"); lines.add("import com.oracle.graal.python.runtime.nativeaccess.NativeLibrary;"); lines.add("import com.oracle.truffle.api.CompilerDirectives;"); diff --git a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/NativeDowncallMethodHandleGenerator.java b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/NativeDowncallMethodHandleGenerator.java index eab9afaf75..cba07e32ee 100644 --- a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/NativeDowncallMethodHandleGenerator.java +++ b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/NativeDowncallMethodHandleGenerator.java @@ -40,7 +40,6 @@ */ package com.oracle.graal.python.processor; -import java.util.ArrayList; import java.util.List; import com.oracle.graal.python.annotations.NativeSimpleType; @@ -60,51 +59,50 @@ static String methodHandleVarName(String signatureName) { return "NATIVE_METHOD_HANDLE_" + signatureName; } - static String toClassLiteral(String javaType) { + private static String toNativeSimpleTypeLiteral(String javaType) { return switch (javaType) { - case "void" -> "void.class"; - case "byte" -> "byte.class"; - case "short" -> "short.class"; - case "int" -> "int.class"; - case "long" -> "long.class"; - case "float" -> "float.class"; - case "double" -> "double.class"; + case "void" -> "NativeSimpleType.VOID"; + case "byte" -> "NativeSimpleType.SINT8"; + case "short" -> "NativeSimpleType.SINT16"; + case "int" -> "NativeSimpleType.SINT32"; + case "long" -> "NativeSimpleType.SINT64"; + case "float" -> "NativeSimpleType.FLOAT"; + case "double" -> "NativeSimpleType.DOUBLE"; default -> throw new IllegalArgumentException("Unexpected Java type: " + javaType); }; } - static String toClassLiteral(NativeSimpleType nativeType) { + private static String toNativeSimpleTypeLiteral(NativeSimpleType nativeType) { return switch (nativeType) { - case VOID -> "void.class"; - case SINT8 -> "byte.class"; - case SINT16 -> "short.class"; - case SINT32 -> "int.class"; - case SINT64, POINTER -> "long.class"; - case FLOAT -> "float.class"; - case DOUBLE -> "double.class"; + case VOID -> "NativeSimpleType.VOID"; + case SINT8 -> "NativeSimpleType.SINT8"; + case SINT16 -> "NativeSimpleType.SINT16"; + case SINT32 -> "NativeSimpleType.SINT32"; + case SINT64 -> "NativeSimpleType.SINT64"; + case FLOAT -> "NativeSimpleType.FLOAT"; + case DOUBLE -> "NativeSimpleType.DOUBLE"; + case POINTER -> "NativeSimpleType.POINTER"; }; } static void emitMethodHandleField(List lines, String fieldName, String returnType, List argTypes) { - List methodTypeArgs = new ArrayList<>(); - methodTypeArgs.add("long.class"); + StringBuilder createHandle = new StringBuilder("NativeAccessSupport.createDowncallHandle(false, false, "); + createHandle.append(toNativeSimpleTypeLiteral(returnType)); for (String argType : argTypes) { - methodTypeArgs.add(toClassLiteral(argType)); + createHandle.append(", ").append(toNativeSimpleTypeLiteral(argType)); } - lines.add(" private static final MethodHandle " + fieldName + " = NativeAccessSupport.createDowncallHandle(" + - "MethodType.methodType(" + toClassLiteral(returnType) + ", " + String.join(", ", methodTypeArgs) + "), false);"); + createHandle.append(")"); + lines.add(" private static final MethodHandle " + fieldName + " = " + createHandle + ";"); } static void emitMethodHandleField(List lines, String fieldName, NativeSimpleType returnType, List argTypes, boolean critical, boolean captureCallState) { - List methodTypeArgs = new ArrayList<>(); - methodTypeArgs.add("long.class"); - if (captureCallState) { - methodTypeArgs.add("MemorySegment.class"); - } + StringBuilder createHandle = new StringBuilder("NativeAccessSupport.createDowncallHandle("); + createHandle.append(critical).append(", ").append(captureCallState).append(", "); + createHandle.append(toNativeSimpleTypeLiteral(returnType)); for (NativeSimpleType argType : argTypes) { - methodTypeArgs.add(toClassLiteral(argType)); + createHandle.append(", ").append(toNativeSimpleTypeLiteral(argType)); } - lines.add(" private static final MethodHandle " + fieldName + " = NativeAccessSupport.createDowncallHandle(" + - "MethodType.methodType(" + toClassLiteral(returnType) + ", " + String.join(", ", methodTypeArgs) + "), " + critical + ", " + captureCallState + ");"); + createHandle.append(")"); + lines.add(" private static final MethodHandle " + fieldName + " = " + createHandle + ";"); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/arrow/ArrowReleaseCallback.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/arrow/ArrowReleaseCallback.java index 85082a0d49..7d08c3021b 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/arrow/ArrowReleaseCallback.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/arrow/ArrowReleaseCallback.java @@ -40,15 +40,16 @@ */ package com.oracle.graal.python.nodes.arrow; +import static com.oracle.graal.python.annotations.NativeSimpleType.POINTER; +import static com.oracle.graal.python.annotations.NativeSimpleType.VOID; + import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; import com.oracle.graal.python.runtime.nativeaccess.NativeAccessSupport; import com.oracle.truffle.api.CompilerDirectives; public final class ArrowReleaseCallback { - private static final MethodHandle HANDLE = NativeAccessSupport.createDowncallHandle( - MethodType.methodType(void.class, long.class, long.class), false); + private static final MethodHandle HANDLE = NativeAccessSupport.createDowncallHandle(false, false, VOID, POINTER); private ArrowReleaseCallback() { } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupport.java index 32e358c078..e6651baf75 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupport.java @@ -104,16 +104,8 @@ static long lookupDefault(String name) { return INSTANCE.lookupDefaultImpl(name); } - static MethodHandle createDowncallHandle(NativeSimpleType resType, NativeSimpleType... argTypes) { - return INSTANCE.createTypedDowncallHandle(resType, argTypes); - } - - public static MethodHandle createDowncallHandle(MethodType methodType, boolean critical) { - return INSTANCE.createDowncallHandleImpl(methodType, critical, false); - } - - public static MethodHandle createDowncallHandle(MethodType methodType, boolean critical, boolean captureCallState) { - return INSTANCE.createDowncallHandleImpl(methodType, critical, captureCallState); + public static MethodHandle createDowncallHandle(boolean critical, boolean captureCallState, NativeSimpleType resType, NativeSimpleType... argTypes) { + return INSTANCE.createDowncallHandleImpl(critical, captureCallState, resType, argTypes); } public static Object createCapturedCallState(Object arena) { @@ -130,10 +122,6 @@ public static int readCapturedGetLastError(Object capturedCallStatePtr) { return INSTANCE.readCapturedGetLastErrorImpl(capturedCallStatePtr); } - static MethodHandle createCapturedDowncallHandle(NativeSimpleType resType, NativeSimpleType... argTypes) { - return INSTANCE.createTypedCapturedDowncallHandle(resType, argTypes); - } - public static boolean isAvailable() { return INSTANCE.isAvailableImpl(); } @@ -146,25 +134,6 @@ public static boolean isCurrentThreadVirtual() { return INSTANCE.isCurrentThreadVirtualImpl(); } - private MethodHandle createTypedDowncallHandle(NativeSimpleType resType, NativeSimpleType... argTypes) { - Class[] parameterTypes = new Class[argTypes.length + 1]; - parameterTypes[0] = long.class; - for (int i = 0; i < argTypes.length; i++) { - parameterTypes[i + 1] = asJavaType(argTypes[i]); - } - return createDowncallHandleImpl(MethodType.methodType(asJavaType(resType), parameterTypes), false, false); - } - - private MethodHandle createTypedCapturedDowncallHandle(NativeSimpleType resType, NativeSimpleType... argTypes) { - Class[] parameterTypes = new Class[argTypes.length + 2]; - parameterTypes[0] = long.class; - parameterTypes[1] = long.class; - for (int i = 0; i < argTypes.length; i++) { - parameterTypes[i + 2] = asJavaType(argTypes[i]); - } - return createDowncallHandleImpl(MethodType.methodType(asJavaType(resType), parameterTypes), false, true); - } - protected abstract Object createArenaImpl(); protected abstract void closeArenaImpl(Object arena); @@ -173,7 +142,7 @@ private MethodHandle createTypedCapturedDowncallHandle(NativeSimpleType resType, protected abstract long lookupDefaultImpl(String name); - protected abstract MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical, boolean captureCallState); + protected abstract MethodHandle createDowncallHandleImpl(boolean critical, boolean captureCallState, NativeSimpleType resType, NativeSimpleType[] argTypes); protected abstract Object createCapturedCallStateImpl(Object arena); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupportJdk21.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupportJdk21.java index e725004f2b..bb3a5f524e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupportJdk21.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeAccessSupportJdk21.java @@ -66,8 +66,21 @@ protected long lookupDefaultImpl(String name) { } @Override - protected MethodHandle createDowncallHandleImpl(MethodType methodType, boolean critical, boolean captureCallState) { - return unsupportedDowncallHandle(methodType); + protected MethodHandle createDowncallHandleImpl(boolean critical, boolean captureCallState, NativeSimpleType resType, NativeSimpleType[] argTypes) { + return unsupportedDowncallHandle(createMethodType(captureCallState, resType, argTypes)); + } + + private static MethodType createMethodType(boolean captureCallState, NativeSimpleType resType, NativeSimpleType... argTypes) { + int injectedArgumentCount = captureCallState ? 2 : 1; + Class[] parameterTypes = new Class[argTypes.length + injectedArgumentCount]; + parameterTypes[0] = long.class; + if (captureCallState) { + parameterTypes[1] = Object.class; + } + for (int i = 0; i < argTypes.length; i++) { + parameterTypes[i + injectedArgumentCount] = asJavaType(argTypes[i]); + } + return MethodType.methodType(asJavaType(resType), parameterTypes); } @Override diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeContext.java index c6af81779d..acc3a6a888 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/nativeaccess/NativeContext.java @@ -112,7 +112,7 @@ public NativeLibrary loadLibrary(String name, int flags) throws NativeLibraryLoa if (isWindows()) { int callFlags = sanitizeWindowsLoadLibraryFlags(flags) | WINDOWS_DEFAULT_LOAD_LIBRARY_FLAGS; Object callStateBuffer = callState.get(); - lib = (long) LOAD_LIBRARY_EX_CAPTURED.invokeExact(loadLibraryExPtr, callStateBuffer, nativeName, 0L, callFlags); + lib = (long) LOAD_LIBRARY_EX_CAPTURED.invoke(loadLibraryExPtr, callStateBuffer, nativeName, 0L, callFlags); } else { int callFlags = flags; if ((callFlags & (RTLD_LAZY | RTLD_NOW)) == 0) { @@ -169,14 +169,14 @@ private static boolean isWindows() { private static final long RTLD_DEFAULT_LINUX = 0L; private static final long RTLD_DEFAULT_DARWIN = -2L; - private static final MethodHandle DLOPEN = NativeAccessSupport.createDowncallHandle(SINT64, POINTER, SINT32); - private static final MethodHandle DLCLOSE = NativeAccessSupport.createDowncallHandle(SINT32, SINT64); - private static final MethodHandle DLSYM = NativeAccessSupport.createDowncallHandle(SINT64, SINT64, POINTER); - private static final MethodHandle FREE_LIBRARY = NativeAccessSupport.createDowncallHandle(SINT32, SINT64); - private static final MethodHandle GET_PROC_ADDRESS = NativeAccessSupport.createDowncallHandle(SINT64, SINT64, POINTER); - private static final MethodHandle FORMAT_MESSAGE = NativeAccessSupport.createDowncallHandle(SINT32, SINT32, POINTER, SINT32, SINT32, POINTER, SINT32, POINTER); - private static final MethodHandle DLERROR = NativeAccessSupport.createDowncallHandle(SINT64); - private static final MethodHandle LOAD_LIBRARY_EX_CAPTURED = isWindows() ? NativeAccessSupport.createCapturedDowncallHandle(SINT64, POINTER, POINTER, SINT32) : null; + private static final MethodHandle DLOPEN = NativeAccessSupport.createDowncallHandle(false, false, SINT64, POINTER, SINT32); + private static final MethodHandle DLCLOSE = NativeAccessSupport.createDowncallHandle(false, false, SINT32, SINT64); + private static final MethodHandle DLSYM = NativeAccessSupport.createDowncallHandle(false, false, SINT64, SINT64, POINTER); + private static final MethodHandle FREE_LIBRARY = NativeAccessSupport.createDowncallHandle(false, false, SINT32, SINT64); + private static final MethodHandle GET_PROC_ADDRESS = NativeAccessSupport.createDowncallHandle(false, false, SINT64, SINT64, POINTER); + private static final MethodHandle FORMAT_MESSAGE = NativeAccessSupport.createDowncallHandle(false, false, SINT32, SINT32, POINTER, SINT32, SINT32, POINTER, SINT32, POINTER); + private static final MethodHandle DLERROR = NativeAccessSupport.createDowncallHandle(false, false, SINT64); + private static final MethodHandle LOAD_LIBRARY_EX_CAPTURED = isWindows() ? NativeAccessSupport.createDowncallHandle(false, true, SINT64, POINTER, POINTER, SINT32) : null; private static long dlopenPtr; private static long dlclosePtr; From 56a4a8ce505a3d5876f4e872cf41421c8bcbb01c Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 25 Jun 2026 12:35:32 +0200 Subject: [PATCH 5/7] Document POSIX errno capture path --- .../graal/python/runtime/NativePosixSupport.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java index 62b6a03dfd..10f2478556 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java @@ -144,8 +144,14 @@ import sun.misc.Unsafe; -/** Implementation that invokes the native POSIX support library through generated native-access - * downcalls. */ +/** + * Implementation that invokes the native POSIX support library through generated native-access + * downcalls. + * + * POSIX calls use a custom errno capture path instead of FFM call-state capture. The native wrapper + * functions store errno in a C thread-local only when the POSIX return value indicates an error. This + * avoids unconditional FFM call-state capture on the hot POSIX path. + */ @ExportLibrary(PosixSupportLibrary.class) public final class NativePosixSupport extends PosixSupport { private static final String SUPPORTING_NATIVE_LIB_NAME = "posix"; From dea30b3297713c482a1268ab8f1cc165b958f33d Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Thu, 25 Jun 2026 22:14:30 +0200 Subject: [PATCH 6/7] Add critical downcall signature support --- .../oracle/graal/python/annotations/DowncallSignature.java | 2 ++ .../python/processor/GenerateNativeDowncallsProcessor.java | 6 ++++-- .../com/oracle/graal/python/runtime/NativePosixSupport.java | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/DowncallSignature.java b/graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/DowncallSignature.java index c0a74428eb..b4d3e008d8 100644 --- a/graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/DowncallSignature.java +++ b/graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/DowncallSignature.java @@ -56,5 +56,7 @@ Class[] argConversions() default {}; + boolean critical() default false; + boolean captureCallState() default false; } diff --git a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java index ac236e6a7f..eb5b9b9c21 100644 --- a/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java +++ b/graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/GenerateNativeDowncallsProcessor.java @@ -63,7 +63,7 @@ import com.oracle.graal.python.annotations.NativeSimpleType; public class GenerateNativeDowncallsProcessor extends AbstractProcessor { - private record NativeDowncallDesc(String name, NativeSimpleType returnType, List argumentTypes, List argumentNames, boolean captureCallState) { + private record NativeDowncallDesc(String name, NativeSimpleType returnType, List argumentTypes, List argumentNames, boolean critical, boolean captureCallState) { } private static final String CAPTURE_CALL_STATE_FIELD = "callState"; @@ -163,7 +163,8 @@ private void generateInvoker(TypeElement invokerElement) throws IOException, Pro lines.add(""); for (NativeDowncallDesc downcall : downcalls) { - NativeDowncallMethodHandleGenerator.emitMethodHandleField(lines, methodHandleName(downcall.name), downcall.returnType, downcall.argumentTypes, false, downcall.captureCallState); + NativeDowncallMethodHandleGenerator.emitMethodHandleField(lines, methodHandleName(downcall.name), downcall.returnType, downcall.argumentTypes, downcall.critical, + downcall.captureCallState); } lines.add(""); @@ -249,6 +250,7 @@ private static NativeDowncallDesc extractDowncall(ExecutableElement method) thro annotation.returnType(), argumentTypes, argumentNames, + annotation.critical(), annotation.captureCallState()); } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java index 10f2478556..bb1b342007 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java @@ -173,7 +173,7 @@ abstract static class PosixNativeFunctionInvoker { @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, SINT32}) abstract int init_constants(long out, int len); - @DowncallSignature(returnType = SINT32) + @DowncallSignature(critical = true, returnType = SINT32) abstract int get_errno(); @DowncallSignature(returnType = SINT64, argumentTypes = {SINT64, SINT32, SINT32, SINT32, SINT64}) From 36c5323c5a16be46f181db26c62f9cd323c0acf5 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Fri, 26 Jun 2026 12:03:11 +0200 Subject: [PATCH 7/7] Revert unnecessary formatting changes --- .../python/runtime/NativePosixSupport.java | 38 ++++++++++++------- .../graal/python/runtime/PythonContext.java | 2 - graalpython/python-libposix/src/fork_exec.c | 6 ++- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java index bb1b342007..5f2e14066e 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NativePosixSupport.java @@ -440,8 +440,10 @@ abstract static class PosixNativeFunctionInvoker { @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER}) abstract int call_unsetenv(long name); - @DowncallSignature(returnType = SINT32, argumentTypes = {POINTER, POINTER, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, - SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, POINTER, SINT64}) + @DowncallSignature(returnType = SINT32, argumentTypes = { + POINTER, POINTER, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, + SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, SINT32, POINTER, SINT64 + }) abstract int fork_exec(long data, long offsets, int offsetsLen, int argsPos, int envPos, int cwdPos, int stdinRdFd, int stdinWrFd, int stdoutRdFd, int stdoutWrFd, int stderrRdFd, int stderrWrFd, int errPipeRdFd, int errPipeWrFd, int closeFds, int restoreSignals, int callSetsid, int pgidToSet, int allowVFork, long fdsToKeep, long fdsToKeepLen); @@ -610,9 +612,11 @@ static NativeLibrary loadNativeLibrary(PythonContext context) { if (PythonLanguage.getPythonOS() == PythonOS.PLATFORM_DARWIN) { return context.ensureNativeContext().getDefaultLibrary(); } - /* We don't want to link the posix support library against libcrypt, because it might + /* + * We don't want to link the posix support library against libcrypt, because it might * not be available on the target Linux system and would make the whole support library - * fail to load. Load it dynamically on demand instead. */ + * fail to load. Load it dynamically on demand instead. + */ try { return context.ensureNativeContext().loadLibrary("libcrypt.so", PosixConstants.RTLD_LOCAL.value); } catch (NativeLibraryLoadException e) { @@ -2006,9 +2010,11 @@ private static long addLengthsOfCStrings(long prevLen, Object[] src) throws Over return PythonUtils.addExact(len, src.length); // add space for terminating '\0' } - /** Copies null-terminated strings to a buffer {@code data} starting at position {@code offset}, + /** + * Copies null-terminated strings to a buffer {@code data} starting at position {@code offset}, * and stores the offset of each string to the {@code offsets} array starting at index - * {@code startPos}. */ + * {@code startPos}. + */ private static long encodeCStringArray(byte[] data, long startOffset, long[] offsets, int startPos, Object[] src) { // The code that calculates dataLen already checked that there is no overflow and that all // offsets fit into an int. @@ -2525,12 +2531,14 @@ public TruffleString crypt(TruffleString word, TruffleString salt, @Exclusive @Cached TruffleString.SwitchEncodingNode switchEncodingToUtf8Node, @Exclusive @Cached TruffleString.CopyToByteArrayNode copyToByteArrayNode, @Exclusive @Cached NativeMemory.ZeroTerminatedUtf8ToTruffleStringNode zeroTerminatedUtf8ToTruffleStringNode) throws PosixException { - /* From the manpage: Upon successful completion, crypt returns a pointer to a string which + /* + * From the manpage: Upon successful completion, crypt returns a pointer to a string which * encodes both the hashed passphrase, and the settings that were used to encode it. See * crypt(5) for more detail on the format of hashed passphrases. crypt places its result in * a static storage area, which will be overwritten by subsequent calls to crypt. It is not * safe to call crypt from multiple threads simultaneously. Upon error, it may return a NULL - * pointer or a pointer to an invalid hash, depending on the implementation. */ + * pointer or a pointer to an invalid hash, depending on the implementation. + */ long wordPtr = NULLPTR; long saltPtr = NULLPTR; try { @@ -2575,7 +2583,8 @@ private TruffleString gai_strerror(Node inliningTarget, int errorCode, NativeMem } } - /** Provides access to {@code struct addrinfo}. + /** + * Provides access to {@code struct addrinfo}. * * The layout of native {@code struct addrinfo} is as follows: * @@ -2590,7 +2599,7 @@ private TruffleString gai_strerror(Node inliningTarget, int errorCode, NativeMem * struct sockaddr *ai_addr; // data copied into socketAddress[] * char *ai_canonname; // longData[0] * struct addrinfo *ai_next; // longData[1] - * }; + * }; * } * * @@ -2607,7 +2616,8 @@ private TruffleString gai_strerror(Node inliningTarget, int errorCode, NativeMem * * It is not clear whether it is guaranteed that {@code ai_family} and * {@code ai_addr->sa_family} are always the same. We provide both and use the later when - * decoding the socket address. */ + * decoding the socket address. + */ private static class AddrInfo { private final int[] intData = new int[7]; private final long[] longData = new long[2]; @@ -2943,8 +2953,10 @@ void semUnlink(Object name) throws PosixException { @ExportMessage int semGetValue(long handle) throws PosixException { - /* msimacek: It works on Linux, and it doesn't work on Darwin. It might work on some other - * Unix-likes, but it's hard to check, so let's assume it only works on Linux for now */ + /* + * msimacek: It works on Linux, and it doesn't work on Darwin. It might work on some other + * Unix-likes, but it's hard to check, so let's assume it only works on Linux for now + */ if (PythonLanguage.getPythonOS() != PythonOS.PLATFORM_LINUX) { throw NO_SEM_GETVALUE_EXCEPTION; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 73a915caad..a771560e41 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -565,7 +565,6 @@ public void dispose(boolean clearNativeThreadLocalVarPointer, boolean markShutti NativeMemory.writePtr(nativeThreadLocalVarPointer, NULLPTR); } nativeThreadLocalVarPointer = NULLPTR; - } public Object getTraceFun() { @@ -659,7 +658,6 @@ public Object getNativeThreadLocalVarPointer() { public boolean isNativeThreadStateInitialized() { return nativeThreadLocalVarPointer != NULLPTR; } - } private static final class AtExitHook { diff --git a/graalpython/python-libposix/src/fork_exec.c b/graalpython/python-libposix/src/fork_exec.c index 397b4cd03d..46005b0b44 100644 --- a/graalpython/python-libposix/src/fork_exec.c +++ b/graalpython/python-libposix/src/fork_exec.c @@ -570,7 +570,8 @@ do_fork_exec(char *const exec_list[], * allowVFork - if nonzero, use vfork() instead of fork() where it is safe and supported * fdsToKeep, fdsToKeepLen - a sorted list of fds to keep open (the child clears their O_CLOEXEC) */ -int32_t fork_exec(char *data, int64_t *offsets, int32_t offsetsLen, int32_t argsPos, int32_t envPos, int32_t cwdPos, +int32_t fork_exec( + char *data, int64_t *offsets, int32_t offsetsLen, int32_t argsPos, int32_t envPos, int32_t cwdPos, int32_t stdinRdFd, int32_t stdinWrFd, int32_t stdoutRdFd, int32_t stdoutWrFd, int32_t stderrRdFd, int32_t stderrWrFd, @@ -580,7 +581,8 @@ int32_t fork_exec(char *data, int64_t *offsets, int32_t offsetsLen, int32_t args int32_t callSetsid, int32_t pgidToSet, int32_t allowVFork, - int32_t *fdsToKeep, int64_t fdsToKeepLen) { + int32_t *fdsToKeep, int64_t fdsToKeepLen + ) { // We reuse the memory allocated for offsets to avoid the need to allocate and reliably free another array char **strings = (char **) offsets;