Skip to content

Commit

Permalink
[GR-54070] Don't let any exceptions slip through out of NFI closures …
Browse files Browse the repository at this point in the history
…on SVM.

PullRequest: graal/17753
  • Loading branch information
rschatz committed May 24, 2024
2 parents 1db13d4 + d08013c commit f53b430
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,17 @@ private enum ClosureArgType {

private final ClosureArgType[] argTypes;

private NativeClosure(CallTarget callTarget, Object receiver, ClosureArgType[] argTypes) {
private final Target_com_oracle_truffle_nfi_backend_libffi_LibFFILanguage language;

private NativeClosure(CallTarget callTarget, Object receiver, ClosureArgType[] argTypes, Target_com_oracle_truffle_nfi_backend_libffi_LibFFILanguage language) {
this.callTarget = new WeakReference<>(callTarget);
if (receiver != null) {
this.receiver = new WeakReference<>(receiver);
} else {
this.receiver = null;
}
this.argTypes = argTypes;
this.language = language;
}

/**
Expand Down Expand Up @@ -130,7 +133,7 @@ static Target_com_oracle_truffle_nfi_backend_libffi_ClosureNativePointer prepare
}
}

NativeClosure closure = new NativeClosure(callTarget, receiver, argTypes);
NativeClosure closure = new NativeClosure(callTarget, receiver, argTypes, ctx.language);
NativeClosureHandle handle = ImageSingletons.lookup(TruffleNFISupport.class).createClosureHandle(closure);

WordPointer codePtr = UnsafeStackValue.get(WordPointer.class);
Expand Down Expand Up @@ -276,24 +279,33 @@ private static int invokeClosureBufferRet0(Pointer ret, WordPointer args, Closur

private static void doInvokeClosureBufferRet(Pointer ret, WordPointer args, ClosureData user) {
NativeClosure closure = lookup(user);
Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_Pointer retBuffer = new Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_Pointer(ret.rawValue());
Target_com_oracle_truffle_nfi_backend_libffi_LibFFIClosure_RetPatches patches = (Target_com_oracle_truffle_nfi_backend_libffi_LibFFIClosure_RetPatches) closure.call(args, retBuffer);

if (patches != null) {
for (int i = 0; i < patches.count; i++) {
Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_TypeTag tag = getTag(patches.patches[i]);
int offset = getOffset(patches.patches[i]);
Object obj = patches.objects[i];

if (tag == Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_TypeTag.OBJECT) {
WordBase handle = ImageSingletons.lookup(TruffleNFISupport.class).createGlobalHandle(obj);
ret.writeWord(offset, handle);
} else if (tag == Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_TypeTag.STRING) {
ret.writeWord(offset, serializeStringRet(obj));
} else {
// nothing to do
try {
Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_Pointer retBuffer = new Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_Pointer(ret.rawValue());
Target_com_oracle_truffle_nfi_backend_libffi_LibFFIClosure_RetPatches patches = (Target_com_oracle_truffle_nfi_backend_libffi_LibFFIClosure_RetPatches) closure.call(args, retBuffer);

if (patches != null) {
for (int i = 0; i < patches.count; i++) {
Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_TypeTag tag = getTag(patches.patches[i]);
int offset = getOffset(patches.patches[i]);
Object obj = patches.objects[i];

if (tag == Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_TypeTag.OBJECT) {
WordBase handle = ImageSingletons.lookup(TruffleNFISupport.class).createGlobalHandle(obj);
ret.writeWord(offset, handle);
} else if (tag == Target_com_oracle_truffle_nfi_backend_libffi_NativeArgumentBuffer_TypeTag.STRING) {
ret.writeWord(offset, serializeStringRet(obj));
} else {
// nothing to do
}
}
}
} catch (Throwable t) {
/*
* Normally no exceptions can happen here, since the NFI frontend already does all the
* exception handling. But certain exceptions can slip through to here, e.g. stack
* overflows or async exceptions from Truffle safepoints.
*/
closure.language.getNFIState().setPendingException(t);
}
}

Expand Down Expand Up @@ -340,7 +352,17 @@ private static int invokeClosureVoidRet0(WordPointer args, ClosureData user, int
}

private static void doInvokeClosureVoidRet(WordPointer args, ClosureData user) {
lookup(user).call(args, null);
NativeClosure closure = lookup(user);
try {
closure.call(args, null);
} catch (Throwable t) {
/*
* Normally no exceptions can happen here, since the NFI frontend already does all the
* exception handling. But certain exceptions can slip through to here, e.g. stack
* overflows or async exceptions from Truffle safepoints.
*/
closure.language.getNFIState().setPendingException(t);
}
}

@CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class, publishAs = Publish.NotPublished)
Expand Down Expand Up @@ -386,8 +408,18 @@ private static int invokeClosureStringRet0(WordPointer ret, WordPointer args, Cl
}

private static void doInvokeClosureStringRet(WordPointer ret, WordPointer args, ClosureData user) {
Object retValue = lookup(user).call(args, null);
ret.write(serializeStringRet(retValue));
NativeClosure closure = lookup(user);
try {
Object retValue = closure.call(args, null);
ret.write(serializeStringRet(retValue));
} catch (Throwable t) {
/*
* Normally no exceptions can happen here, since the NFI frontend already does all the
* exception handling. But certain exceptions can slip through to here, e.g. stack
* overflows or async exceptions from Truffle safepoints.
*/
closure.language.getNFIState().setPendingException(t);
}
}

@CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class, publishAs = Publish.NotPublished)
Expand Down Expand Up @@ -433,12 +465,22 @@ private static int invokeClosureObjectRet0(WordPointer ret, WordPointer args, Cl
}

private static void doInvokeClosureObjectRet(WordPointer ret, WordPointer args, ClosureData user) {
Object obj = lookup(user).call(args, null);
if (obj == null) {
ret.write(WordFactory.zero());
} else {
TruffleObjectHandle handle = ImageSingletons.lookup(TruffleNFISupport.class).createGlobalHandle(obj);
ret.write(handle);
NativeClosure closure = lookup(user);
try {
Object obj = closure.call(args, null);
if (obj == null) {
ret.write(WordFactory.zero());
} else {
TruffleObjectHandle handle = ImageSingletons.lookup(TruffleNFISupport.class).createGlobalHandle(obj);
ret.write(handle);
}
} catch (Throwable t) {
/*
* Normally no exceptions can happen here, since the NFI frontend already does all the
* exception handling. But certain exceptions can slip through to here, e.g. stack
* overflows or async exceptions from Truffle safepoints.
*/
closure.language.getNFIState().setPendingException(t);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@
final class Target_com_oracle_truffle_nfi_backend_spi_NFIState {

@Alias boolean hasPendingException;

@Alias
native void setPendingException(Throwable t);
}

0 comments on commit f53b430

Please sign in to comment.