Skip to content

Commit 5ac34e6

Browse files
committed
[GR-18163] The exit code should be 1 if there is an internal error while running at_exit hooks
PullRequest: truffleruby/3892
2 parents ec4bbc5 + a0a2a37 commit 5ac34e6

File tree

5 files changed

+54
-14
lines changed

5 files changed

+54
-14
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
slow:Internal errors reaching the top level show both the Java stacktrace and Ruby backtrace
22
slow:Internal errors reaching the top level show the cause
33
slow:Internal errors reaching the top level AssertionError in another Thread is rethrown on the main Ruby Thread
4+
slow:Internal errors reaching the top level are also reported if they happen in at_exit
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. This
2+
# code is released under a tri EPL/GPL/LGPL license. You can use it,
3+
# redistribute it and/or modify it under the terms of the:
4+
#
5+
# Eclipse Public License version 2.0, or
6+
# GNU General Public License version 2, or
7+
# GNU Lesser General Public License version 2.1.
8+
9+
def foo
10+
Truffle::Debug.throw_java_exception 'custom message'
11+
end
12+
13+
at_exit do
14+
foo
15+
end

spec/truffle/java_exception_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,30 @@
3333
EOS
3434
end
3535

36+
it "are also reported if they happen in at_exit" do
37+
file = fixture(__FILE__, 'throw_java_exception_at_exit.rb')
38+
out = ruby_exe(file, args: "2>&1", exit_status: 1)
39+
out = out.gsub(/\.java:\d+/, '.java:LINE')
40+
out.should == <<-EOS
41+
42+
truffleruby: unexpected internal exception in at_exit,
43+
please report it to https://github.com/oracle/truffleruby/issues.
44+
45+
```
46+
custom message (java.lang.RuntimeException)
47+
from org.truffleruby.debug.TruffleDebugNodes$ThrowJavaExceptionNode.throwingMethod(TruffleDebugNodes.java:LINE)
48+
from org.truffleruby.debug.TruffleDebugNodes$ThrowJavaExceptionNode.callingMethod(TruffleDebugNodes.java:LINE)
49+
from org.truffleruby.debug.TruffleDebugNodes$ThrowJavaExceptionNode.throwJavaException(TruffleDebugNodes.java:LINE)
50+
from org.truffleruby.debug.TruffleDebugNodesFactory$ThrowJavaExceptionNodeFactory$ThrowJavaExceptionNodeGen.executeAndSpecialize(TruffleDebugNodesFactory.java:LINE)
51+
from org.truffleruby.debug.TruffleDebugNodesFactory$ThrowJavaExceptionNodeFactory$ThrowJavaExceptionNodeGen.execute(TruffleDebugNodesFactory.java:LINE)
52+
from org.truffleruby.language.RubyCoreMethodRootNode.execute(RubyCoreMethodRootNode.java:LINE)
53+
#{file}:10:in `throw_java_exception'
54+
from #{file}:10:in `foo'
55+
from #{file}:14:in `block in <main>'
56+
```
57+
EOS
58+
end
59+
3660
it "show the cause" do
3761
file = fixture(__FILE__, 'throw_java_exception_with_cause.rb')
3862
out = ruby_exe(file, args: "2>&1", exit_status: 1)

src/main/java/org/truffleruby/core/kernel/AtExitManager.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,21 @@ public void add(RubyProc block, boolean always) {
4848
}
4949

5050
public AbstractTruffleException runAtExitHooks() {
51-
return runExitHooks(atExitHooks, "at_exit");
51+
return runExitHooks(atExitHooks);
5252
}
5353

5454
public void runSystemExitHooks() {
55-
runExitHooks(systemExitHooks, "system at_exit");
55+
try {
56+
runExitHooks(systemExitHooks);
57+
} catch (ExitException | ThreadDeath e) {
58+
throw e;
59+
} catch (RuntimeException | Error e) {
60+
BacktraceFormatter.printInternalError(context, e, "unexpected internal exception in system at_exit");
61+
}
5662
}
5763

5864
@TruffleBoundary
59-
private AbstractTruffleException runExitHooks(Deque<RubyProc> stack, String name) {
65+
private AbstractTruffleException runExitHooks(Deque<RubyProc> stack) {
6066
AbstractTruffleException lastException = null;
6167

6268
while (true) {
@@ -67,13 +73,9 @@ private AbstractTruffleException runExitHooks(Deque<RubyProc> stack, String name
6773

6874
try {
6975
ProcOperations.rootCall(block, EmptyArgumentsDescriptor.INSTANCE, RubyBaseNode.EMPTY_ARGUMENTS);
70-
} catch (ExitException | ThreadDeath e) {
71-
throw e;
7276
} catch (AbstractTruffleException e) {
7377
handleAtExitException(context, e);
7478
lastException = e;
75-
} catch (RuntimeException | Error e) {
76-
BacktraceFormatter.printInternalError(context, e, "Unexpected internal exception in " + name);
7779
}
7880
}
7981
}

src/main/java/org/truffleruby/language/exceptions/TopLevelRaiseHandler.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,21 @@ public int execute(Runnable body) {
5656
// No FiberShutdownException, it's only for Fibers
5757
assert !(e instanceof FiberShutdownException) : e;
5858

59-
BacktraceFormatter.printInternalError(
60-
getContext(),
61-
e,
59+
BacktraceFormatter.printInternalError(getContext(), e,
6260
"an internal exception escaped out of the interpreter");
6361
return 1;
6462
}
6563

6664
// Execute at_exit hooks (except if hard #exit!)
65+
String step = "unexpected internal exception in at_exit";
6766
try {
6867
AbstractTruffleException atExitException = getContext().getAtExitManager().runAtExitHooks();
68+
6969
if (atExitException != null) {
7070
exitCode = statusFromException(atExitException);
7171
}
7272

73+
step = "an internal exception escaped out of the interpreter";
7374
if (caughtException != null) {
7475
// print the main script exception now
7576
if (!AtExitManager.isSilentException(getContext(), caughtException)) {
@@ -84,10 +85,7 @@ public int execute(Runnable body) {
8485
} catch (ThreadDeath e) { // Context#close(true)
8586
throw e;
8687
} catch (RuntimeException | Error e) { // Internal error
87-
BacktraceFormatter.printInternalError(
88-
getContext(),
89-
e,
90-
"an internal exception escaped out of the interpreter");
88+
BacktraceFormatter.printInternalError(getContext(), e, step);
9189
return 1;
9290
}
9391

0 commit comments

Comments
 (0)