Skip to content

Commit 8a3908e

Browse files
committed
[GR-27621] Move printInternalError() to BacktraceFormatter and use it in AtExitManager
PullRequest: truffleruby/2199
2 parents 7e9bf06 + b85aa8e commit 8a3908e

File tree

3 files changed

+77
-87
lines changed

3 files changed

+77
-87
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.truffleruby.core.exception.RubySystemExit;
2020
import org.truffleruby.core.proc.ProcOperations;
2121
import org.truffleruby.core.proc.RubyProc;
22+
import org.truffleruby.language.backtrace.BacktraceFormatter;
2223
import org.truffleruby.language.control.ExitException;
2324
import org.truffleruby.language.control.RaiseException;
2425

@@ -69,9 +70,8 @@ private RubyException runExitHooks(Deque<RubyProc> stack, String name) {
6970
lastException = e.getException();
7071
} catch (ExitException e) {
7172
throw e;
72-
} catch (Exception e) {
73-
System.err.println("Unexpected internal exception in " + name + ":");
74-
e.printStackTrace();
73+
} catch (RuntimeException | Error e) {
74+
BacktraceFormatter.printInternalError(context, e, "Unexpected internal exception in " + name);
7575
}
7676
}
7777
}

src/main/java/org/truffleruby/language/backtrace/BacktraceFormatter.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
import com.oracle.truffle.api.CompilerDirectives;
1313
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
14+
import com.oracle.truffle.api.TruffleStackTrace;
1415
import com.oracle.truffle.api.TruffleStackTraceElement;
16+
import com.oracle.truffle.api.exception.AbstractTruffleException;
1517
import com.oracle.truffle.api.nodes.Node;
1618
import com.oracle.truffle.api.nodes.RootNode;
1719
import com.oracle.truffle.api.source.Source;
@@ -28,6 +30,7 @@
2830
import org.truffleruby.core.string.StringOperations;
2931
import org.truffleruby.core.string.StringUtils;
3032
import org.truffleruby.language.RubyRootNode;
33+
import org.truffleruby.language.control.RaiseException;
3134
import org.truffleruby.language.methods.TranslateExceptionNode;
3235
import org.truffleruby.parser.RubySource;
3336

@@ -369,4 +372,67 @@ public static String formatJavaThrowableMessage(Throwable t) {
369372
return (message != null ? message : "<no message>") + " (" + t.getClass().getCanonicalName() + ")";
370373
}
371374

375+
@TruffleBoundary
376+
public static void printInternalError(RubyContext context, Throwable throwable, String from) {
377+
final PrintStream stream = BacktraceFormatter.printStreamFor(context.getEnv().err());
378+
final BacktraceFormatter formatter = context.getDefaultBacktraceFormatter();
379+
stream.println();
380+
stream.println("truffleruby: " + from + ",");
381+
stream.println("please report it to https://github.com/oracle/truffleruby/issues.");
382+
stream.println();
383+
stream.println("```");
384+
385+
boolean firstException = true;
386+
Throwable t = throwable;
387+
388+
while (t != null) {
389+
if (t.getClass().getSimpleName().equals("LazyStackTrace")) {
390+
// Truffle's lazy stracktrace support, not a real exception
391+
break;
392+
}
393+
394+
if (!firstException) {
395+
stream.println("Caused by:");
396+
}
397+
398+
if (t instanceof RaiseException) {
399+
// A Ruby exception as a cause of a Java or C-ext exception
400+
final RubyException rubyException = ((RaiseException) t).getException();
401+
402+
final String formattedBacktrace = formatter
403+
.formatBacktrace(rubyException, rubyException.backtrace);
404+
stream.println(formattedBacktrace);
405+
} else {
406+
stream.println(formatJavaThrowableMessage(t));
407+
408+
if (t instanceof AbstractTruffleException) {
409+
// Foreign exception
410+
stream.println(formatter.formatBacktrace(null, new Backtrace((AbstractTruffleException) t)));
411+
} else {
412+
// Internal error, print it formatted like a Ruby exception
413+
printJavaStackTrace(stream, t);
414+
415+
if (TruffleStackTrace.getStackTrace(t) != null) {
416+
stream.println(formatter.formatBacktrace(null, new Backtrace(t)));
417+
}
418+
}
419+
}
420+
421+
t = t.getCause();
422+
firstException = false;
423+
}
424+
425+
stream.println("```");
426+
}
427+
428+
private static void printJavaStackTrace(PrintStream stream, Throwable t) {
429+
final StackTraceElement[] stackTrace = t.getStackTrace();
430+
for (StackTraceElement stackTraceElement : stackTrace) {
431+
stream.println("\tfrom " + stackTraceElement);
432+
if (BacktraceInterleaver.isCallBoundary(stackTraceElement)) {
433+
break;
434+
}
435+
}
436+
}
437+
372438
}

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

Lines changed: 8 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,18 @@
99
*/
1010
package org.truffleruby.language.exceptions;
1111

12-
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
13-
import com.oracle.truffle.api.TruffleStackTrace;
14-
import com.oracle.truffle.api.exception.AbstractTruffleException;
1512
import org.truffleruby.core.exception.RubyException;
1613
import org.truffleruby.core.exception.RubySystemExit;
1714
import org.truffleruby.core.kernel.AtExitManager;
1815
import org.truffleruby.core.thread.GetCurrentRubyThreadNode;
1916
import org.truffleruby.language.RubyContextNode;
20-
import org.truffleruby.language.backtrace.Backtrace;
2117
import org.truffleruby.language.backtrace.BacktraceFormatter;
22-
import org.truffleruby.language.backtrace.BacktraceInterleaver;
2318
import org.truffleruby.language.control.ExitException;
2419
import org.truffleruby.language.control.RaiseException;
2520
import org.truffleruby.language.dispatch.DispatchNode;
2621

2722
import com.oracle.truffle.api.CompilerDirectives;
2823

29-
import java.io.PrintStream;
30-
import java.util.EnumSet;
31-
3224
public class TopLevelRaiseHandler extends RubyContextNode {
3325

3426
@Child private GetCurrentRubyThreadNode getCurrentRubyThreadNode;
@@ -49,7 +41,10 @@ public int execute(Runnable body) {
4941
// hard #exit!, return immediately, skip at_exit hooks
5042
return e.getCode();
5143
} catch (RuntimeException | Error e) {
52-
printInternalError(e);
44+
BacktraceFormatter.printInternalError(
45+
getContext(),
46+
e,
47+
"an internal exception escaped out of the interpreter");
5348
return 1;
5449
}
5550

@@ -72,7 +67,10 @@ public int execute(Runnable body) {
7267
// hard #exit! during at_exit: ignore the main script exception
7368
exitCode = e.getCode();
7469
} catch (RuntimeException | Error e) { // Internal error
75-
printInternalError(e);
70+
BacktraceFormatter.printInternalError(
71+
getContext(),
72+
e,
73+
"an internal exception escaped out of the interpreter");
7674
return 1;
7775
}
7876

@@ -103,78 +101,4 @@ private void handleSignalException(RubyException exception) {
103101
}
104102
}
105103

106-
@TruffleBoundary
107-
private void printInternalError(Throwable throwable) {
108-
final PrintStream stream = BacktraceFormatter.printStreamFor(getContext().getEnv().err());
109-
stream.println();
110-
stream.println("truffleruby: an internal exception escaped out of the interpreter,");
111-
stream.println("please report it to https://github.com/oracle/truffleruby/issues.");
112-
stream.println();
113-
stream.println("```");
114-
115-
boolean firstException = true;
116-
Throwable t = throwable;
117-
118-
while (t != null) {
119-
if (t.getClass().getSimpleName().equals("LazyStackTrace")) {
120-
// Truffle's lazy stracktrace support, not a real exception
121-
break;
122-
}
123-
124-
if (!firstException) {
125-
stream.println("Caused by:");
126-
}
127-
128-
if (t instanceof RaiseException) {
129-
// A Ruby exception as a cause of a Java or C-ext exception
130-
final RubyException rubyException = ((RaiseException) t).getException();
131-
132-
final BacktraceFormatter formatter = new BacktraceFormatter(
133-
getContext(),
134-
getLanguage(),
135-
EnumSet.noneOf(BacktraceFormatter.FormattingFlags.class));
136-
final String formattedBacktrace = formatter
137-
.formatBacktrace(rubyException, rubyException.backtrace);
138-
stream.println(formattedBacktrace);
139-
} else {
140-
stream.println(BacktraceFormatter.formatJavaThrowableMessage(t));
141-
142-
if (t instanceof AbstractTruffleException) {
143-
// Foreign exception
144-
printTruffleStackTrace(stream, new Backtrace((AbstractTruffleException) t));
145-
} else {
146-
// Internal error, print it formatted like a Ruby exception
147-
printJavaStackTrace(stream, t);
148-
149-
if (TruffleStackTrace.getStackTrace(t) != null) {
150-
printTruffleStackTrace(stream, new Backtrace(t));
151-
}
152-
}
153-
}
154-
155-
t = t.getCause();
156-
firstException = false;
157-
}
158-
159-
stream.println("```");
160-
}
161-
162-
private void printTruffleStackTrace(PrintStream stream, Backtrace backtrace) {
163-
final BacktraceFormatter formatter = new BacktraceFormatter(
164-
getContext(),
165-
getLanguage(),
166-
EnumSet.noneOf(BacktraceFormatter.FormattingFlags.class));
167-
stream.println(formatter.formatBacktrace(null, backtrace));
168-
}
169-
170-
private void printJavaStackTrace(PrintStream stream, Throwable t) {
171-
final StackTraceElement[] stackTrace = t.getStackTrace();
172-
for (StackTraceElement stackTraceElement : stackTrace) {
173-
stream.println("\tfrom " + stackTraceElement);
174-
if (BacktraceInterleaver.isCallBoundary(stackTraceElement)) {
175-
break;
176-
}
177-
}
178-
}
179-
180104
}

0 commit comments

Comments
 (0)