diff --git a/CHANGELOG.md b/CHANGELOG.md index da707ff38a36..3a2521dfeba6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Bug fixes: * Fix `Proc#parameters` and return all the numbered parameters lower than the used explicitly ones (@andrykonchin). * Fix some C API functions which were failing when called with Ruby values represented as Java primitives (#3352, @eregon). * Fix `IO.select([io], nil, [io])` on macOS, it was hanging due to a bug in macOS `poll(2)` (#3346, @eregon, @andrykonchin). +* Run context cleanup such as showing the output of tools when `SignalException` and `Interrupt` escape (@eregon). Compatibility: diff --git a/mx.truffleruby/eclipse-settings/org.eclipse.jdt.core.prefs b/mx.truffleruby/eclipse-settings/org.eclipse.jdt.core.prefs index cb6c0490968e..806d494e72c0 100644 --- a/mx.truffleruby/eclipse-settings/org.eclipse.jdt.core.prefs +++ b/mx.truffleruby/eclipse-settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,5 @@ org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=disabled org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore @@ -6,6 +7,7 @@ org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=ignore org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false diff --git a/mx.truffleruby/suite.py b/mx.truffleruby/suite.py index 971a85cdfcd9..99d4fed60912 100644 --- a/mx.truffleruby/suite.py +++ b/mx.truffleruby/suite.py @@ -207,12 +207,22 @@ "license": ["EPL-2.0"], }, - "org.truffleruby.rubysignal": { + "org.truffleruby.signal": { + "dir": "src/signal", + "sourceDirs": ["java"], + "jniHeaders": True, + "javaCompliance": "17+", + "checkstyle": "org.truffleruby", + "workingSets": "TruffleRuby", + "license": ["EPL-2.0"], + }, + + "org.truffleruby.librubysignal": { "dir": "src/main/c/rubysignal", "native": "shared_lib", "deliverable": "rubysignal", "buildDependencies": [ - "org.truffleruby", # for the generated JNI header file + "org.truffleruby.signal", # for the generated JNI header file ], "use_jdk_headers": True, # the generated JNI header includes jni.h "cflags": ["-g", "-Wall", "-Werror", "-pthread"], @@ -245,7 +255,6 @@ "org.truffleruby": { "dir": "src/main", "sourceDirs": ["java"], - "jniHeaders": True, "requires": [ "java.logging", "java.management", @@ -278,6 +287,7 @@ "checkstyle": "org.truffleruby", "workingSets": "TruffleRuby", "findbugsIgnoresGenerated": True, + "forceJavac": True, # GR-51148 We need to force javac to silence a ECJ warning in generated code "license": [ "EPL-2.0", # JRuby (we're choosing EPL out of EPL,GPL,LGPL) "BSD-new", # Rubinius @@ -449,11 +459,13 @@ "exports": [ "org.truffleruby.shared to org.graalvm.ruby, org.graalvm.ruby.launcher", "org.truffleruby.shared.options to org.graalvm.ruby, org.graalvm.ruby.launcher", + "org.truffleruby.signal to org.graalvm.ruby, org.graalvm.ruby.launcher", ], }, "useModulePath": True, "dependencies": [ - "org.truffleruby.shared" + "org.truffleruby.shared", + "org.truffleruby.signal", ], "distDependencies": [ "truffleruby:TRUFFLERUBY-ANNOTATIONS", @@ -700,7 +712,7 @@ "dependency:org.truffleruby.cext/src/main/c/truffleposix/", "dependency:org.truffleruby.cext/src/main/c/cext/", "dependency:org.truffleruby.cext/src/main/c/cext-trampoline/", - "dependency:org.truffleruby.rubysignal", + "dependency:org.truffleruby.librubysignal", ], # The platform-specific files from debug and rbs, see comment above "lib/gems/": "file:lib/gems/extensions", diff --git a/spec/truffle/signal_exception_spec.rb b/spec/truffle/signal_exception_spec.rb deleted file mode 100644 index 8f85c88391aa..000000000000 --- a/spec/truffle/signal_exception_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved. This -# code is released under a tri EPL/GPL/LGPL license. You can use it, -# redistribute it and/or modify it under the terms of the: -# -# Eclipse Public License version 2.0, or -# GNU General Public License version 2, or -# GNU Lesser General Public License version 2.1. - -require_relative '../ruby/spec_helper' - -describe "SignalException" do - # Differs from MRI - it "does not self-signal for VTALRM" do - IO.popen([*ruby_exe, "-e", "raise(SignalException, 'VTALRM')"], err: [:child, :out]) do |out| - out.read.should include("for SIGVTALRM as it is VM reserved") - end - $?.termsig.should == nil - $?.exitstatus.should == 1 - end -end diff --git a/src/launcher/java/org/truffleruby/launcher/RubyLauncher.java b/src/launcher/java/org/truffleruby/launcher/RubyLauncher.java index 71131a1f13e0..cdc1eebdb426 100644 --- a/src/launcher/java/org/truffleruby/launcher/RubyLauncher.java +++ b/src/launcher/java/org/truffleruby/launcher/RubyLauncher.java @@ -29,15 +29,19 @@ import org.graalvm.polyglot.PolyglotException; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; +import org.truffleruby.shared.ProcessStatus; +import org.truffleruby.shared.Platform; import org.truffleruby.shared.Metrics; import org.truffleruby.shared.TruffleRuby; import org.truffleruby.shared.options.OptionsCatalog; +import org.truffleruby.signal.LibRubySignal; public class RubyLauncher extends AbstractLanguageLauncher { private CommandLineOptions config; private String implementationName = null; private boolean helpOptionUsed = false; // Any --help* option + private String rubyHome = null; /** NOTE: not actually used by thin launchers. The first method called with the arguments is * {@link #preprocessArguments}. */ @@ -292,30 +296,51 @@ private int runRubyMain(Context.Builder contextBuilder, CommandLineOptions confi contextBuilder.arguments(TruffleRuby.LANGUAGE_ID, config.getArguments()); - int result = runContext(contextBuilder, config); + int processStatus = runContext(contextBuilder, config); final boolean runTwice = config.getUnknownArguments().contains("--run-twice") || config.getUnknownArguments().contains("--run-twice=true"); if (runTwice) { final int secondResult = runContext(contextBuilder, config); - if (secondResult != 0 && result == 0) { - result = secondResult; + if (secondResult != 0 && processStatus == 0) { + processStatus = secondResult; } } - return result; + // SignalExeption exit, we need to raise(3) the native signal to set the correct process waitpid(3) status + if (ProcessStatus.isSignal(processStatus)) { + int signalNumber = ProcessStatus.toSignal(processStatus); + + if (rubyHome != null) { + LibRubySignal.loadLibrary(rubyHome, Platform.LIB_SUFFIX); + LibRubySignal.restoreSystemHandlerAndRaise(signalNumber); + // Some signals are ignored by default, such as SIGWINCH and SIGCHLD, in that exit with 1 like CRuby + return 1; + } else { + System.err.println("The TruffleRuby context ended with signal " + signalNumber + + " but since librubysignal is not found we exit with code " + signalNumber + + " instead of raising the signal"); + return signalNumber; + } + } + + return processStatus; } private int runContext(Context.Builder builder, CommandLineOptions config) { try (Context context = builder.build()) { Metrics.printTime("before-run"); + Value rubyHome = context.eval(source( + // language=ruby + "Truffle::Boot.ruby_home")); + if (rubyHome.isString()) { + this.rubyHome = rubyHome.asString(); + } + if (config.executionAction == ExecutionAction.PATH) { - final Source source = Source.newBuilder( - TruffleRuby.LANGUAGE_ID, - // language=ruby - "-> name { Truffle::Boot.find_s_file(name) }", - TruffleRuby.BOOT_SOURCE_NAME).internal(true).buildLiteral(); + final Source source = source(// language=ruby + "-> name { Truffle::Boot.find_s_file(name) }"); config.executionAction = ExecutionAction.FILE; final Value file = context.eval(source).execute(config.toExecute); @@ -329,34 +354,35 @@ private int runContext(Context.Builder builder, CommandLineOptions config) { } if (config.logProcessArguments) { - Value logInfo = context.eval( - "ruby", + Value logInfo = context.eval(source( // language=ruby - "-> message { Truffle::Debug.log_info(message) }"); + "-> message { Truffle::Debug.log_info(message) }")); String message = "new process: truffleruby " + String.join(" ", config.initialArguments); logInfo.executeVoid(message); } - final Source source = Source.newBuilder( - TruffleRuby.LANGUAGE_ID, - // language=ruby - "-> argc, argv, kind, to_execute { Truffle::Boot.main(argc, argv, kind, to_execute) }", - TruffleRuby.BOOT_SOURCE_NAME).internal(true).buildLiteral(); + final Source source = source(// language=ruby + "-> argc, argv, kind, to_execute { Truffle::Boot.main(argc, argv, kind, to_execute) }"); final int argc = getNativeArgc(); final long argv = getNativeArgv(); final String kind = config.executionAction.name(); - final int exitCode = context.eval(source).execute(argc, argv, kind, config.toExecute).asInt(); + final int processStatus = context.eval(source).execute(argc, argv, kind, config.toExecute).asInt(); Metrics.printTime("after-run"); - return exitCode; + return processStatus; } catch (PolyglotException e) { getError().println( "truffleruby: an exception escaped out of the interpreter - this is an implementation bug"); - e.printStackTrace(); + e.printStackTrace(System.err); return 1; } } + private static Source source(String code) { + return Source.newBuilder(TruffleRuby.LANGUAGE_ID, code, TruffleRuby.BOOT_SOURCE_NAME).internal(true) + .buildLiteral(); + } + private static List getArgsFromEnvVariable(String name) { String value = System.getenv(name); if (value != null) { diff --git a/src/main/c/rubysignal/src/rubysignal.c b/src/main/c/rubysignal/src/rubysignal.c index 6f54043462be..3b35e79ce67b 100644 --- a/src/main/c/rubysignal/src/rubysignal.c +++ b/src/main/c/rubysignal/src/rubysignal.c @@ -37,11 +37,16 @@ JNIEXPORT jint JNICALL Java_org_truffleruby_signal_LibRubySignal_sendSIGVTALRMTo } JNIEXPORT jlong JNICALL Java_org_truffleruby_signal_LibRubySignal_getNativeThreadID(JNIEnv *env, jclass clazz) { - #ifdef __APPLE__ - uint64_t native_id; - pthread_threadid_np(NULL, &native_id); - #elif defined(__linux__) - pid_t native_id = (pid_t) syscall(SYS_gettid); - #endif - return (jlong) native_id; +#ifdef __APPLE__ + uint64_t native_id; + pthread_threadid_np(NULL, &native_id); +#elif defined(__linux__) + pid_t native_id = (pid_t) syscall(SYS_gettid); +#endif + return (jlong) native_id; +} + +JNIEXPORT void JNICALL Java_org_truffleruby_signal_LibRubySignal_restoreSystemHandlerAndRaise(JNIEnv *env, jclass clazz, jint signo) { + signal(signo, SIG_DFL); + raise(signo); } diff --git a/src/main/java/org/truffleruby/RubyLanguage.java b/src/main/java/org/truffleruby/RubyLanguage.java index 7e700d485dc4..5147fbb9db7a 100644 --- a/src/main/java/org/truffleruby/RubyLanguage.java +++ b/src/main/java/org/truffleruby/RubyLanguage.java @@ -116,7 +116,7 @@ import org.truffleruby.parser.ParsingParameters; import org.truffleruby.parser.RubySource; import org.truffleruby.parser.TranslatorEnvironment; -import org.truffleruby.platform.Platform; +import org.truffleruby.shared.Platform; import org.truffleruby.shared.Metrics; import org.truffleruby.shared.TruffleRuby; import org.truffleruby.shared.options.OptionsCatalog; diff --git a/src/main/java/org/truffleruby/cext/ValueWrapperManager.java b/src/main/java/org/truffleruby/cext/ValueWrapperManager.java index fdc441d7d7b9..bdc4a38d6b93 100644 --- a/src/main/java/org/truffleruby/cext/ValueWrapperManager.java +++ b/src/main/java/org/truffleruby/cext/ValueWrapperManager.java @@ -215,12 +215,6 @@ public static final class HandleBlock { @SuppressWarnings("unused") private Cleanable cleanable; - private HandleBlock() { - base = 0; - cleanable = null; - wrappers = null; - } - public HandleBlock(RubyContext context, RubyLanguage language, ValueWrapperManager manager) { HandleBlockAllocator allocator = language.handleBlockAllocator; long base = allocator.getFreeBlock(); diff --git a/src/main/java/org/truffleruby/collections/ConcurrentWeakSet.java b/src/main/java/org/truffleruby/collections/ConcurrentWeakSet.java index 09bb9da8e111..f3b6649cd85a 100644 --- a/src/main/java/org/truffleruby/collections/ConcurrentWeakSet.java +++ b/src/main/java/org/truffleruby/collections/ConcurrentWeakSet.java @@ -32,7 +32,7 @@ public Object[] toArray() { @TruffleBoundary public WeakSetIterator iterator() { - return new WeakSetIterator(map.keySet().iterator()); + return new WeakSetIterator<>(map.keySet().iterator()); } private static final class WeakSetIterator implements Iterator { diff --git a/src/main/java/org/truffleruby/core/TruffleSystemNodes.java b/src/main/java/org/truffleruby/core/TruffleSystemNodes.java index 4af90f2200ce..76ffc84bdfba 100644 --- a/src/main/java/org/truffleruby/core/TruffleSystemNodes.java +++ b/src/main/java/org/truffleruby/core/TruffleSystemNodes.java @@ -69,8 +69,7 @@ import org.truffleruby.language.RubyGuards; import org.truffleruby.language.control.RaiseException; import org.truffleruby.language.library.RubyStringLibrary; -import org.truffleruby.platform.Platform; -import org.truffleruby.shared.BasicPlatform; +import org.truffleruby.shared.Platform; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; @@ -214,7 +213,7 @@ public abstract static class HostCPUNode extends CoreMethodNode { @Specialization RubyString hostCPU() { - return createString(fromJavaStringNode, BasicPlatform.getArchName(), Encodings.UTF_8); + return createString(fromJavaStringNode, Platform.getArchName(), Encodings.UTF_8); } } diff --git a/src/main/java/org/truffleruby/core/array/ArrayConcatNode.java b/src/main/java/org/truffleruby/core/array/ArrayConcatNode.java index 9a1f6d50b896..576b363e774f 100644 --- a/src/main/java/org/truffleruby/core/array/ArrayConcatNode.java +++ b/src/main/java/org/truffleruby/core/array/ArrayConcatNode.java @@ -81,6 +81,7 @@ public void doExecuteVoid(VirtualFrame frame) { } } + @Override public RubyNode cloneUninitialized() { var copy = new ArrayConcatNode(cloneUninitialized(children)); return copy.copyFlags(this); diff --git a/src/main/java/org/truffleruby/core/array/library/DoubleArrayStore.java b/src/main/java/org/truffleruby/core/array/library/DoubleArrayStore.java index 1708b2799572..e63e6889252b 100644 --- a/src/main/java/org/truffleruby/core/array/library/DoubleArrayStore.java +++ b/src/main/java/org/truffleruby/core/array/library/DoubleArrayStore.java @@ -165,7 +165,7 @@ static void sort(double[] store, int size) { @ExportMessage static Iterable getIterable(double[] store, int from, int length) { - return () -> new Iterator() { + return () -> new Iterator<>() { private int n = from; diff --git a/src/main/java/org/truffleruby/core/array/library/IntegerArrayStore.java b/src/main/java/org/truffleruby/core/array/library/IntegerArrayStore.java index 1d88d7e3d4af..b4347f316c07 100644 --- a/src/main/java/org/truffleruby/core/array/library/IntegerArrayStore.java +++ b/src/main/java/org/truffleruby/core/array/library/IntegerArrayStore.java @@ -165,7 +165,7 @@ static void sort(int[] store, int size) { @ExportMessage static Iterable getIterable(int[] store, int from, int length) { - return () -> new Iterator() { + return () -> new Iterator<>() { private int n = from; diff --git a/src/main/java/org/truffleruby/core/array/library/LongArrayStore.java b/src/main/java/org/truffleruby/core/array/library/LongArrayStore.java index 25ecb003c3b4..5f2fa7b86174 100644 --- a/src/main/java/org/truffleruby/core/array/library/LongArrayStore.java +++ b/src/main/java/org/truffleruby/core/array/library/LongArrayStore.java @@ -186,7 +186,7 @@ static void sort(long[] store, int size) { @ExportMessage static Iterable getIterable(long[] store, int from, int length) { - return () -> new Iterator() { + return () -> new Iterator<>() { private int n = from; diff --git a/src/main/java/org/truffleruby/core/array/library/NativeArrayStorage.java b/src/main/java/org/truffleruby/core/array/library/NativeArrayStorage.java index 22c714fa759e..19a701202e5b 100644 --- a/src/main/java/org/truffleruby/core/array/library/NativeArrayStorage.java +++ b/src/main/java/org/truffleruby/core/array/library/NativeArrayStorage.java @@ -221,7 +221,7 @@ protected Object[] toJavaArrayCopy(int size, @ExportMessage static Iterable getIterable(NativeArrayStorage store, int from, int length, @CachedLibrary("store") ArrayStoreLibrary stores) { - return () -> new Iterator() { + return () -> new Iterator<>() { private int n = from; diff --git a/src/main/java/org/truffleruby/core/array/library/ObjectArrayStore.java b/src/main/java/org/truffleruby/core/array/library/ObjectArrayStore.java index ae8340571eac..4f1fb71970e2 100644 --- a/src/main/java/org/truffleruby/core/array/library/ObjectArrayStore.java +++ b/src/main/java/org/truffleruby/core/array/library/ObjectArrayStore.java @@ -160,7 +160,7 @@ static Object[] toJavaArrayCopy(Object[] store, int length) { @ExportMessage static Iterable getIterable(Object[] store, int from, int length) { - return () -> new Iterator() { + return () -> new Iterator<>() { private int n = from; diff --git a/src/main/java/org/truffleruby/core/fiber/FiberManager.java b/src/main/java/org/truffleruby/core/fiber/FiberManager.java index 69f27541cb7d..be6847dbbc5c 100644 --- a/src/main/java/org/truffleruby/core/fiber/FiberManager.java +++ b/src/main/java/org/truffleruby/core/fiber/FiberManager.java @@ -478,10 +478,6 @@ public RubyFiber getSendingFiber() { return sendingFiber; } - public ArgumentsDescriptor getDescriptor() { - return descriptor; - } - public Object[] getArgs() { return args; } diff --git a/src/main/java/org/truffleruby/core/format/rbsprintf/RBSprintfCompiler.java b/src/main/java/org/truffleruby/core/format/rbsprintf/RBSprintfCompiler.java index 1e44e09e5622..156defbc7aad 100644 --- a/src/main/java/org/truffleruby/core/format/rbsprintf/RBSprintfCompiler.java +++ b/src/main/java/org/truffleruby/core/format/rbsprintf/RBSprintfCompiler.java @@ -42,7 +42,7 @@ public RootCallTarget compile(AbstractTruffleString formatTString, RubyEncoding Object stringReader) { var byteArray = formatTString.getInternalByteArrayUncached(formatEncoding.tencoding); - final RBSprintfSimpleParser parser = new RBSprintfSimpleParser(StringSupport.bytesToChars(byteArray), false); + final RBSprintfSimpleParser parser = new RBSprintfSimpleParser(StringSupport.bytesToChars(byteArray)); final List configs = parser.parse(); final RBSprintfSimpleTreeBuilder builder = new RBSprintfSimpleTreeBuilder(configs, stringReader, formatEncoding); @@ -60,7 +60,7 @@ public RubyArray typeList(AbstractTruffleString formatTString, RubyEncoding form TruffleString.GetInternalByteArrayNode byteArrayNode, RubyContext context, RubyLanguage language) { var byteArray = byteArrayNode.execute(formatTString, formatEncoding.tencoding); - final RBSprintfSimpleParser parser = new RBSprintfSimpleParser(StringSupport.bytesToChars(byteArray), false); + final RBSprintfSimpleParser parser = new RBSprintfSimpleParser(StringSupport.bytesToChars(byteArray)); final List configs = parser.parse(); final int[] types = new int[3 * configs.size()]; // Ensure there is enough space for the argument types that might be in the format string. diff --git a/src/main/java/org/truffleruby/core/format/rbsprintf/RBSprintfSimpleParser.java b/src/main/java/org/truffleruby/core/format/rbsprintf/RBSprintfSimpleParser.java index d9fa125fbebd..4888da0d61e2 100644 --- a/src/main/java/org/truffleruby/core/format/rbsprintf/RBSprintfSimpleParser.java +++ b/src/main/java/org/truffleruby/core/format/rbsprintf/RBSprintfSimpleParser.java @@ -20,11 +20,9 @@ public final class RBSprintfSimpleParser { private final char[] source; - private final boolean isDebug; - public RBSprintfSimpleParser(char[] source, boolean isDebug) { + public RBSprintfSimpleParser(char[] source) { this.source = source; - this.isDebug = isDebug; } public List parse() { @@ -32,7 +30,6 @@ public List parse() { ArgType argType = ArgType.NONE; final int end = source.length; - int argCount = 0; for (int i = 0; i < end;) { @@ -137,7 +134,6 @@ public List parse() { i = numberDollarWidth.getNextI(); } else { checkNextArg(argType, 1); // TODO index next args - argCount += 1; argType = ArgType.UNNUMBERED; config.setWidthStar(true); i++; @@ -161,7 +157,6 @@ public List parse() { i = numberDollar.getNextI(); } else { checkNextArg(argType, 1); // TODO idx - argCount += 1; argType = ArgType.UNNUMBERED; config.setPrecisionStar(true); i += 2; @@ -243,7 +238,6 @@ public List parse() { i++; if (!argTypeSet) { // Speculative checkNextArg(argType, 1); - argCount += 1; argType = ArgType.UNNUMBERED; } finished = true; @@ -256,7 +250,6 @@ public List parse() { i++; if (!argTypeSet) { // Speculative checkNextArg(argType, 1); - argCount += 1; argType = ArgType.UNNUMBERED; } finished = true; @@ -280,7 +273,6 @@ public List parse() { config.setFormat(p); if (!argTypeSet) { // Speculative checkNextArg(argType, 1); - argCount += 1; argType = ArgType.UNNUMBERED; } finished = true; @@ -295,7 +287,6 @@ public List parse() { } if (!argTypeSet) { checkNextArg(argType, 1); // TODO idx correctly - argCount += 1; argType = ArgType.UNNUMBERED; } config.setFormatType(RBSprintfConfig.FormatType.INTEGER); @@ -316,7 +307,6 @@ public List parse() { } if (!argTypeSet) { checkNextArg(argType, 1); - argCount += 1; argType = ArgType.UNNUMBERED; } config.setFormatType(RBSprintfConfig.FormatType.FLOAT); diff --git a/src/main/java/org/truffleruby/core/inlined/InlinedLessOrEqualNode.java b/src/main/java/org/truffleruby/core/inlined/InlinedLessOrEqualNode.java index ba8179f759a5..47360aaf6d06 100644 --- a/src/main/java/org/truffleruby/core/inlined/InlinedLessOrEqualNode.java +++ b/src/main/java/org/truffleruby/core/inlined/InlinedLessOrEqualNode.java @@ -56,6 +56,7 @@ Object fallback(VirtualFrame frame, Object a, Object b) { return rewriteAndCall(frame, a, b); } + @Override public RubyNode cloneUninitialized() { var copy = InlinedLessOrEqualNodeGen.create( getLanguage(), diff --git a/src/main/java/org/truffleruby/core/module/ModuleNodes.java b/src/main/java/org/truffleruby/core/module/ModuleNodes.java index 22f86f37761e..cc87292c857c 100644 --- a/src/main/java/org/truffleruby/core/module/ModuleNodes.java +++ b/src/main/java/org/truffleruby/core/module/ModuleNodes.java @@ -1377,6 +1377,7 @@ public Object execute(VirtualFrame frame) { return lambdaBody.execute(frame); } + @Override public RubyNode cloneUninitialized() { var copy = new CallMethodWithLambdaBody( proc, diff --git a/src/main/java/org/truffleruby/core/regexp/ClassicRegexp.java b/src/main/java/org/truffleruby/core/regexp/ClassicRegexp.java index 7354bdc10022..e5fb22e9b274 100644 --- a/src/main/java/org/truffleruby/core/regexp/ClassicRegexp.java +++ b/src/main/java/org/truffleruby/core/regexp/ClassicRegexp.java @@ -70,7 +70,6 @@ import org.truffleruby.parser.RubyDeferredWarnings; public final class ClassicRegexp implements ReOptions { - private final RubyContext context; private final Regex pattern; private final TStringWithEncoding str; private RegexpOptions options; @@ -114,9 +113,8 @@ private static Regex getRegexpFromCache(TStringBuilder bytes, RubyEncoding encod return newRegex; } - public ClassicRegexp(RubyContext context, TStringWithEncoding strEnc, RegexpOptions originalOptions) + public ClassicRegexp(TStringWithEncoding strEnc, RegexpOptions originalOptions) throws DeferredRaiseException { - this.context = context; this.options = originalOptions; if (strEnc.encoding.isDummy) { diff --git a/src/main/java/org/truffleruby/core/regexp/RegexpNodes.java b/src/main/java/org/truffleruby/core/regexp/RegexpNodes.java index bc7665c1b612..4f7d660da1b6 100644 --- a/src/main/java/org/truffleruby/core/regexp/RegexpNodes.java +++ b/src/main/java/org/truffleruby/core/regexp/RegexpNodes.java @@ -127,7 +127,6 @@ protected TStringWithEncoding createTString(RubyRegexp regexp) { try { classicRegexp = new ClassicRegexp( - getContext(), new TStringWithEncoding(regexp.source, regexp.encoding), RegexpOptions.fromEmbeddedOptions(regexp.regex.getOptions())); } catch (DeferredRaiseException dre) { diff --git a/src/main/java/org/truffleruby/core/rescue/AssignRescueVariableNode.java b/src/main/java/org/truffleruby/core/rescue/AssignRescueVariableNode.java index 042cb99e7c27..7539ddbe1540 100644 --- a/src/main/java/org/truffleruby/core/rescue/AssignRescueVariableNode.java +++ b/src/main/java/org/truffleruby/core/rescue/AssignRescueVariableNode.java @@ -38,6 +38,7 @@ public Object execute(VirtualFrame frame) { return nil; } + @Override public RubyNode cloneUninitialized() { var copy = new AssignRescueVariableNode(rescueVariableNode.cloneUninitializedAssignable()); return copy.copyFlags(this); diff --git a/src/main/java/org/truffleruby/core/thread/ThreadManager.java b/src/main/java/org/truffleruby/core/thread/ThreadManager.java index 68b057d3daad..dd92cab2a404 100644 --- a/src/main/java/org/truffleruby/core/thread/ThreadManager.java +++ b/src/main/java/org/truffleruby/core/thread/ThreadManager.java @@ -65,6 +65,7 @@ import com.oracle.truffle.api.TruffleStackTrace; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.object.Shape; +import org.truffleruby.shared.Platform; import org.truffleruby.signal.LibRubySignal; public final class ThreadManager { @@ -102,7 +103,7 @@ public void initialize() { language.getRubyHome() != null; nativeInterrupt = context.getOptions().NATIVE_INTERRUPT && useLibRubySignal; if (useLibRubySignal) { - LibRubySignal.loadLibrary(language.getRubyHome()); + LibRubySignal.loadLibrary(language.getRubyHome(), Platform.LIB_SUFFIX); } if (nativeInterrupt) { LibRubySignal.setupSIGVTALRMEmptySignalHandler(); diff --git a/src/main/java/org/truffleruby/debug/TruffleDebugNodes.java b/src/main/java/org/truffleruby/debug/TruffleDebugNodes.java index d5f58dcfa4d7..135c7edc2b85 100644 --- a/src/main/java/org/truffleruby/debug/TruffleDebugNodes.java +++ b/src/main/java/org/truffleruby/debug/TruffleDebugNodes.java @@ -114,9 +114,9 @@ import org.truffleruby.parser.YARPTranslatorDriver; import org.truffleruby.parser.parser.ParserConfiguration; import org.truffleruby.parser.scope.StaticScope; -import org.truffleruby.platform.Platform; import org.prism.Loader; import org.prism.Parser; +import org.truffleruby.shared.Platform; @CoreModule("Truffle::Debug") public abstract class TruffleDebugNodes { diff --git a/src/main/java/org/truffleruby/language/RubyDynamicObject.java b/src/main/java/org/truffleruby/language/RubyDynamicObject.java index b1ef797548a6..0954b2ae1219 100644 --- a/src/main/java/org/truffleruby/language/RubyDynamicObject.java +++ b/src/main/java/org/truffleruby/language/RubyDynamicObject.java @@ -64,8 +64,6 @@ @ExportLibrary(InteropLibrary.class) public abstract class RubyDynamicObject extends DynamicObject { - private static final int FROZEN = 1; - private RubyClass metaClass; public RubyDynamicObject(RubyClass metaClass, Shape shape) { diff --git a/src/main/java/org/truffleruby/language/RubyNode.java b/src/main/java/org/truffleruby/language/RubyNode.java index e3cd419d4993..b10f90996076 100644 --- a/src/main/java/org/truffleruby/language/RubyNode.java +++ b/src/main/java/org/truffleruby/language/RubyNode.java @@ -334,6 +334,7 @@ Object getRootInstance(Frame frame, method); } + @Override public abstract RubyNode cloneUninitialized(); public static RubyNode cloneUninitialized(RubyNode node) { diff --git a/src/main/java/org/truffleruby/language/WarnNode.java b/src/main/java/org/truffleruby/language/WarnNode.java index f865106aae3b..a357d02d7959 100644 --- a/src/main/java/org/truffleruby/language/WarnNode.java +++ b/src/main/java/org/truffleruby/language/WarnNode.java @@ -110,6 +110,7 @@ public static final class UncachedWarnNode extends AbstractUncachedWarnNode { UncachedWarnNode() { } + @Override public boolean shouldWarn() { return coreLibrary().warningsEnabled(); } diff --git a/src/main/java/org/truffleruby/language/arguments/ReadKeywordArgumentNode.java b/src/main/java/org/truffleruby/language/arguments/ReadKeywordArgumentNode.java index 5309e6519289..4a474bbc2c28 100644 --- a/src/main/java/org/truffleruby/language/arguments/ReadKeywordArgumentNode.java +++ b/src/main/java/org/truffleruby/language/arguments/ReadKeywordArgumentNode.java @@ -29,6 +29,7 @@ /** Read a single keyword argument or execute its default value expression if missing */ @ImportStatic(HashGuards.class) +@SuppressWarnings("all") public abstract class ReadKeywordArgumentNode extends RubyContextSourceNode implements PEBiFunction { private final RubySymbol name; @@ -40,6 +41,12 @@ public static ReadKeywordArgumentNode create(RubySymbol name, RubyNode defaultVa return ReadKeywordArgumentNodeGen.create(name, defaultValue); } + protected ReadKeywordArgumentNode(RubySymbol name, RubyNode defaultValue) { + this.name = name; + this.defaultValue = defaultValue; + this.readUserKeywordsHashNode = new ReadUserKeywordsHashNode(); + } + public RubySymbol getName() { return name; } @@ -51,18 +58,13 @@ public final Object execute(VirtualFrame frame) { public abstract Object execute(VirtualFrame frame, RubyHash hash); - protected ReadKeywordArgumentNode(RubySymbol name, RubyNode defaultValue) { - this.name = name; - this.defaultValue = defaultValue; - readUserKeywordsHashNode = new ReadUserKeywordsHashNode(); - } - @Specialization(guards = "hash == null") + @Specialization(guards = "isNull(hash)") Object nullHash(VirtualFrame frame, RubyHash hash) { return getDefaultValue().execute(frame); } - @Specialization(guards = "hash != null", limit = "hashStrategyLimit()") + @Specialization(guards = "!isNull(hash)", limit = "hashStrategyLimit()") Object lookupKeywordInHash(VirtualFrame frame, RubyHash hash, @CachedLibrary("getHashStore(hash)") HashStoreLibrary hashes) { return hashes.lookupOrDefault(hash.store, frame, hash, name, this); @@ -74,6 +76,11 @@ protected Object getHashStore(RubyHash hash) { return hash == null ? EmptyHashStore.NULL_HASH_STORE : hash.store; } + // Workaround for ECJ to not warn about dead code in generated code + static boolean isNull(RubyHash hash) { + return hash == null; + } + @Override public Object accept(Frame frame, Object hash, Object key) { // This only works if the library is always cached and does not reach the limit. diff --git a/src/main/java/org/truffleruby/language/constants/OrAssignConstantNode.java b/src/main/java/org/truffleruby/language/constants/OrAssignConstantNode.java index fbb26e5b05ca..cdeef24622f7 100644 --- a/src/main/java/org/truffleruby/language/constants/OrAssignConstantNode.java +++ b/src/main/java/org/truffleruby/language/constants/OrAssignConstantNode.java @@ -77,6 +77,7 @@ Object doOrAssignConstant(VirtualFrame frame, } } + @Override public RubyNode cloneUninitialized() { var copy = OrAssignConstantNodeGen.create( (ReadConstantNode) readConstant.cloneUninitialized(), diff --git a/src/main/java/org/truffleruby/language/constants/ReadConstantWithLexicalScopeNode.java b/src/main/java/org/truffleruby/language/constants/ReadConstantWithLexicalScopeNode.java index e197ff5c93d1..92ee967c6dc4 100644 --- a/src/main/java/org/truffleruby/language/constants/ReadConstantWithLexicalScopeNode.java +++ b/src/main/java/org/truffleruby/language/constants/ReadConstantWithLexicalScopeNode.java @@ -63,6 +63,7 @@ public Object isDefined(VirtualFrame frame, RubyLanguage language, RubyContext c } } + @Override public RubyNode cloneUninitialized() { var copy = new ReadConstantWithLexicalScopeNode(lexicalScope, name); return copy.copyFlags(this); diff --git a/src/main/java/org/truffleruby/language/control/DeferredRaiseException.java b/src/main/java/org/truffleruby/language/control/DeferredRaiseException.java index 26aecea97e85..d0acb22149e6 100644 --- a/src/main/java/org/truffleruby/language/control/DeferredRaiseException.java +++ b/src/main/java/org/truffleruby/language/control/DeferredRaiseException.java @@ -31,6 +31,8 @@ public interface ExceptionGetter { RubyException getException(RubyContext context); } + @SuppressWarnings("sync-override") + @Override public Throwable fillInStackTrace() { return this; } diff --git a/src/main/java/org/truffleruby/language/control/NotNode.java b/src/main/java/org/truffleruby/language/control/NotNode.java index 6506ecabe734..46fdb08ca206 100644 --- a/src/main/java/org/truffleruby/language/control/NotNode.java +++ b/src/main/java/org/truffleruby/language/control/NotNode.java @@ -32,6 +32,7 @@ Object doNot(VirtualFrame frame, return !valueAsBoolean; } + @Override public RubyNode cloneUninitialized() { var copy = NotNodeGen.create(child.cloneUninitialized()); return copy.copyFlags(this); diff --git a/src/main/java/org/truffleruby/language/control/UnlessNode.java b/src/main/java/org/truffleruby/language/control/UnlessNode.java index 0167350f4cfc..071a40c44d38 100644 --- a/src/main/java/org/truffleruby/language/control/UnlessNode.java +++ b/src/main/java/org/truffleruby/language/control/UnlessNode.java @@ -54,7 +54,7 @@ public RubyNode simplifyAsTailExpression() { return UnlessNodeGen.create(condition, thenBody.simplifyAsTailExpression()).copySourceSection(this); } - + @Override public RubyNode cloneUninitialized() { var copy = UnlessNodeGen.create( condition.cloneUninitialized(), diff --git a/src/main/java/org/truffleruby/language/control/WhileNode.java b/src/main/java/org/truffleruby/language/control/WhileNode.java index 0df8f519ffd6..afb899337dd6 100644 --- a/src/main/java/org/truffleruby/language/control/WhileNode.java +++ b/src/main/java/org/truffleruby/language/control/WhileNode.java @@ -38,6 +38,7 @@ public Object execute(VirtualFrame frame) { return nil; } + @Override public RubyNode cloneUninitialized() { var repeatingNode = (WhileRepeatingBaseNode) loopNode.getRepeatingNode(); var copy = new WhileNode(repeatingNode.cloneUninitialized()); diff --git a/src/main/java/org/truffleruby/language/dispatch/InternalRespondToNode.java b/src/main/java/org/truffleruby/language/dispatch/InternalRespondToNode.java index db42ada586c6..d1656a7a7773 100644 --- a/src/main/java/org/truffleruby/language/dispatch/InternalRespondToNode.java +++ b/src/main/java/org/truffleruby/language/dispatch/InternalRespondToNode.java @@ -98,6 +98,7 @@ protected Uncached(DispatchConfiguration config) { super(config, null, null); } + @Override public boolean execute(Frame frame, Object receiver, String methodName) { return executeInternal(frame, receiver, methodName, config, diff --git a/src/main/java/org/truffleruby/language/exceptions/TopLevelRaiseHandler.java b/src/main/java/org/truffleruby/language/exceptions/TopLevelRaiseHandler.java index 20b9ca01cf06..58cd589b92fe 100644 --- a/src/main/java/org/truffleruby/language/exceptions/TopLevelRaiseHandler.java +++ b/src/main/java/org/truffleruby/language/exceptions/TopLevelRaiseHandler.java @@ -26,9 +26,11 @@ import org.truffleruby.language.control.RaiseException; import org.truffleruby.language.dispatch.DispatchNode; import org.truffleruby.language.objects.IsANode; +import org.truffleruby.shared.ProcessStatus; public final class TopLevelRaiseHandler extends RubyBaseNode { + // Must use ProcessStatus.exitCode() or ProcessStatus.signal() for every return @TruffleBoundary public int execute(Runnable body) { int exitCode = 0; @@ -39,7 +41,7 @@ public int execute(Runnable body) { body.run(); } catch (ExitException e) { // hard #exit!, return immediately, skip at_exit hooks - return e.getCode(); + return ProcessStatus.exitCode(e.getCode()); } catch (AbstractTruffleException e) { // No KillException, it's a SystemExit instead for the main thread assert !(e instanceof KillException) : e; @@ -58,7 +60,7 @@ public int execute(Runnable body) { BacktraceFormatter.printInternalError(getContext(), e, "an internal exception escaped out of the interpreter"); - return 1; + return ProcessStatus.exitCode(1); } // Execute at_exit hooks (except if hard #exit!) @@ -77,7 +79,10 @@ public int execute(Runnable body) { getContext().getDefaultBacktraceFormatter().printTopLevelRubyExceptionOnEnvStderr(caughtException); } - handleSignalException(caughtException); + int signo = handleSignalException(caughtException); + if (signo != 0) { + return ProcessStatus.signal(signo); + } } } catch (ExitException e) { // hard #exit! during at_exit: ignore the main script exception @@ -86,10 +91,10 @@ public int execute(Runnable body) { throw e; } catch (RuntimeException | Error e) { // Internal error BacktraceFormatter.printInternalError(getContext(), e, step); - return 1; + return ProcessStatus.exitCode(1); } - return exitCode; + return ProcessStatus.exitCode(exitCode); } private int statusFromException(AbstractTruffleException exception) { @@ -105,16 +110,17 @@ private int statusFromException(AbstractTruffleException exception) { } } - /** See rb_ec_cleanup() in CRuby, which calls ruby_default_signal(), which uses raise(3). */ - private void handleSignalException(AbstractTruffleException exception) { + /** See rb_ec_cleanup() in CRuby, which calls ruby_default_signal(), which uses raise(3). We need to raise(3) after + * Context#close for e.g. letting tools print their output, so just return the signal number here. */ + private int handleSignalException(AbstractTruffleException exception) { if (exception instanceof RaiseException) { RubyException rubyException = ((RaiseException) exception).getException(); if (IsANode.getUncached().executeIsA(rubyException, coreLibrary().signalExceptionClass)) { - // Calls raise(3) or no-op - DispatchNode.getUncached().call(rubyException, "reached_top_level"); + return (int) DispatchNode.getUncached().call(rubyException, "signo"); } } + return 0; } } diff --git a/src/main/java/org/truffleruby/language/loader/FeatureLoader.java b/src/main/java/org/truffleruby/language/loader/FeatureLoader.java index 45ac00611928..3901f81b3db6 100644 --- a/src/main/java/org/truffleruby/language/loader/FeatureLoader.java +++ b/src/main/java/org/truffleruby/language/loader/FeatureLoader.java @@ -46,8 +46,8 @@ import org.truffleruby.language.control.RaiseException; import org.truffleruby.language.dispatch.DispatchNode; import org.truffleruby.platform.NativeConfiguration; -import org.truffleruby.platform.Platform; import org.truffleruby.platform.TruffleNFIPlatform; +import org.truffleruby.shared.Platform; import org.truffleruby.shared.Metrics; import org.truffleruby.shared.TruffleRuby; diff --git a/src/main/java/org/truffleruby/language/methods/BlockDefinitionNode.java b/src/main/java/org/truffleruby/language/methods/BlockDefinitionNode.java index 7af0a7e87a69..5f63eafad6de 100644 --- a/src/main/java/org/truffleruby/language/methods/BlockDefinitionNode.java +++ b/src/main/java/org/truffleruby/language/methods/BlockDefinitionNode.java @@ -54,6 +54,7 @@ public BreakID getBreakID() { return breakID; } + @Override public abstract RubyProc execute(VirtualFrame virtualFrame); @Specialization diff --git a/src/main/java/org/truffleruby/language/objects/WriteInstanceVariableNode.java b/src/main/java/org/truffleruby/language/objects/WriteInstanceVariableNode.java index f58a542d9a83..aeffe27a84d1 100644 --- a/src/main/java/org/truffleruby/language/objects/WriteInstanceVariableNode.java +++ b/src/main/java/org/truffleruby/language/objects/WriteInstanceVariableNode.java @@ -35,6 +35,7 @@ public abstract class WriteInstanceVariableNode extends RubyContextSourceNode im @CompilationFinal private boolean frozenProfile; + @Override public abstract Object execute(VirtualFrame frame); public WriteInstanceVariableNode(String name, RubyNode rhs) { diff --git a/src/main/java/org/truffleruby/parser/PatternMatchingTranslator.java b/src/main/java/org/truffleruby/parser/PatternMatchingTranslator.java index 8087085c3125..f79f90d9910d 100644 --- a/src/main/java/org/truffleruby/parser/PatternMatchingTranslator.java +++ b/src/main/java/org/truffleruby/parser/PatternMatchingTranslator.java @@ -208,6 +208,7 @@ public RubyNode visitArrayPatternNode(ArrayPatternParseNode arrayPatternParseNod return sequence(sourceSection, Arrays.asList(assignTemp, condition)); } + @Override public RubyNode visitFindPatternNode(FindPatternParseNode findPatternParseNode) { return findPatternParseNode.accept(this); } diff --git a/src/main/java/org/truffleruby/parser/YARPTranslator.java b/src/main/java/org/truffleruby/parser/YARPTranslator.java index 1d8f64a8c3ac..5875e1a21077 100644 --- a/src/main/java/org/truffleruby/parser/YARPTranslator.java +++ b/src/main/java/org/truffleruby/parser/YARPTranslator.java @@ -200,7 +200,7 @@ public class YARPTranslator extends AbstractNodeVisitor { private boolean translatingWhile = false; private boolean translatingNextExpression = false; - private boolean translatingForStatement = false; + @SuppressWarnings("unused") private boolean translatingForStatement = false; private static final String[] numberedParameterNames = { null, diff --git a/src/main/java/org/truffleruby/parser/YARPTranslatorDriver.java b/src/main/java/org/truffleruby/parser/YARPTranslatorDriver.java index 6e38488f09e3..bdcc67afddd0 100644 --- a/src/main/java/org/truffleruby/parser/YARPTranslatorDriver.java +++ b/src/main/java/org/truffleruby/parser/YARPTranslatorDriver.java @@ -82,7 +82,7 @@ import org.truffleruby.parser.lexer.RubyLexer; import org.truffleruby.parser.parser.ParserConfiguration; import org.truffleruby.parser.scope.StaticScope; -import org.truffleruby.platform.Platform; +import org.truffleruby.shared.Platform; import org.truffleruby.shared.Metrics; import org.prism.Loader; import org.prism.Nodes; @@ -443,18 +443,14 @@ public static org.prism.Nodes.Node parseToYARPAST(RubyContext context, RubyLangu SourceSection section = rubySource.getSource().createSection(location.startOffset, location.length); String message = context.fileLine(section) + ": " + error.message; - if (context != null) { - int lineNumber = RubySource.getStartLineAdjusted(context, section); + int lineNumber = RubySource.getStartLineAdjusted(context, section); - throw new RaiseException( - context, - context.getCoreExceptions().syntaxErrorAlreadyWithFileLine( - message, - null, - rubySource.getSource().createSection(lineNumber))); - } else { - throw new UnsupportedOperationException(message); - } + throw new RaiseException( + context, + context.getCoreExceptions().syntaxErrorAlreadyWithFileLine( + message, + null, + rubySource.getSource().createSection(lineNumber))); } for (var magicComment : parseResult.magicComments) { diff --git a/src/main/java/org/truffleruby/parser/parser/ParserSupport.java b/src/main/java/org/truffleruby/parser/parser/ParserSupport.java index be3656d993de..f086eb9b3aa9 100644 --- a/src/main/java/org/truffleruby/parser/parser/ParserSupport.java +++ b/src/main/java/org/truffleruby/parser/parser/ParserSupport.java @@ -1832,7 +1832,6 @@ private void allocateNamedLocals(RegexpParseNode regexpNode) { final ClassicRegexp pattern; try { pattern = new ClassicRegexp( - configuration.getContext(), regexpNode.getValue(), regexpNode.getOptions()); } catch (DeferredRaiseException dre) { @@ -1935,7 +1934,7 @@ public TStringWithEncoding setRegexpEncoding(RegexpParseNode end, TStringWithEnc protected ClassicRegexp checkRegexpSyntax(TStringWithEncoding value, RegexpOptions options) { try { // This is only for syntax checking but this will as a side effect create an entry in the regexp cache. - return new ClassicRegexp(getConfiguration().getContext(), value, options); + return new ClassicRegexp(value, options); } catch (DeferredRaiseException dre) { throw compile_error(dre.getException(getConfiguration().getContext()).getMessage()); } catch (RaiseException re) { diff --git a/src/main/java/org/truffleruby/parser/parser/RubyParser.java b/src/main/java/org/truffleruby/parser/parser/RubyParser.java index c94147d3dc19..aa9dfc8938ff 100644 --- a/src/main/java/org/truffleruby/parser/parser/RubyParser.java +++ b/src/main/java/org/truffleruby/parser/parser/RubyParser.java @@ -43,8 +43,6 @@ import com.oracle.truffle.api.strings.TruffleString; import java.util.Set; -import org.jcodings.Encoding; -import org.jcodings.specific.UTF8Encoding; import org.truffleruby.Layouts; import org.truffleruby.annotations.SuppressFBWarnings; @@ -156,7 +154,7 @@ // @formatter:off // CheckStyle: start generated @SuppressFBWarnings("IP") -@SuppressWarnings({"unchecked", "fallthrough", "cast"}) +@SuppressWarnings({"unchecked", "fallthrough", "cast", "rawtypes"}) public final class RubyParser { private final ParserSupport support; private final RubyLexer lexer; @@ -166,7 +164,7 @@ public RubyParser(LexerSource source, RubyDeferredWarnings warnings) { this.lexer = new RubyLexer(support, source, warnings); support.setLexer(lexer); } -// line 134 "-" +// line 132 "-" // %token constants public static final int keyword_class = 257; public static final int keyword_module = 258; @@ -3549,8 +3547,8 @@ public Object yyparse (RubyLexer yyLex) { }; states[561] = (support, lexer, yyVal, yyVals, yyTop) -> { /* TODO: make a helper for this since it is used twice now*/ - Encoding encoding = support.getConfiguration().getContext() == null ? UTF8Encoding.INSTANCE : support.getConfiguration().getContext().getEncodingManager().getLocaleEncoding().jcoding; - yyVal = new FileParseNode(lexer.getPosition(), TruffleString.fromJavaStringUncached(lexer.getFile(), lexer.tencoding), lexer.encoding); + RubyEncoding encoding = support.getConfiguration().getContext() == null ? Encodings.UTF_8 : support.getConfiguration().getContext().getEncodingManager().getLocaleEncoding(); + yyVal = new FileParseNode(lexer.tokline, TStringUtils.fromJavaString(lexer.getFile(), encoding), encoding); return yyVal; }; states[562] = (support, lexer, yyVal, yyVals, yyTop) -> { @@ -4492,7 +4490,7 @@ public Object yyparse (RubyLexer yyLex) { return yyVal; }; } -// line 3249 "RubyParser.y" +// line 3247 "RubyParser.y" /** The parse method use an lexer stream and parse it to an AST node * structure @@ -4509,4 +4507,4 @@ public RubyParserResult parse(ParserConfiguration configuration) { } // CheckStyle: stop generated // @formatter:on -// line 12094 "-" +// line 12092 "-" diff --git a/src/main/java/org/truffleruby/parser/parser/RubyParser.y b/src/main/java/org/truffleruby/parser/parser/RubyParser.y index 3c447a51d6c1..ed5cb621a439 100644 --- a/src/main/java/org/truffleruby/parser/parser/RubyParser.y +++ b/src/main/java/org/truffleruby/parser/parser/RubyParser.y @@ -4,8 +4,6 @@ package org.truffleruby.parser.parser; import com.oracle.truffle.api.strings.TruffleString; import java.util.Set; -import org.jcodings.Encoding; -import org.jcodings.specific.UTF8Encoding; import org.truffleruby.Layouts; import org.truffleruby.annotations.SuppressFBWarnings; @@ -117,7 +115,7 @@ import static org.truffleruby.parser.parser.ParserSupport.value_expr; // @formatter:off // CheckStyle: start generated @SuppressFBWarnings("IP") -@SuppressWarnings({"unchecked", "fallthrough", "cast"}) +@SuppressWarnings({"unchecked", "fallthrough", "cast", "rawtypes"}) public final class RubyParser { private final ParserSupport support; private final RubyLexer lexer; @@ -2390,8 +2388,8 @@ p_primitive : literal } | keyword__FILE__ { // TODO: make a helper for this since it is used twice now - Encoding encoding = support.getConfiguration().getContext() == null ? UTF8Encoding.INSTANCE : support.getConfiguration().getContext().getEncodingManager().getLocaleEncoding().jcoding; - $$ = new FileParseNode(lexer.getPosition(), TruffleString.fromJavaStringUncached(lexer.getFile(), lexer.tencoding), lexer.encoding); + RubyEncoding encoding = support.getConfiguration().getContext() == null ? Encodings.UTF_8 : support.getConfiguration().getContext().getEncodingManager().getLocaleEncoding(); + $$ = new FileParseNode(lexer.tokline, TStringUtils.fromJavaString(lexer.getFile(), encoding), encoding); } | keyword__LINE__ { $$ = new FixnumParseNode(lexer.tokline, lexer.getRubySourceLine()); diff --git a/src/main/java/org/truffleruby/platform/NativeConfiguration.java b/src/main/java/org/truffleruby/platform/NativeConfiguration.java index f9a3fab72a1c..fe3ce026453e 100644 --- a/src/main/java/org/truffleruby/platform/NativeConfiguration.java +++ b/src/main/java/org/truffleruby/platform/NativeConfiguration.java @@ -48,6 +48,7 @@ import org.truffleruby.language.objects.ObjectGraph; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import org.truffleruby.shared.Platform; public final class NativeConfiguration { diff --git a/src/main/java/org/truffleruby/platform/Platform.java b/src/main/java/org/truffleruby/platform/Platform.java deleted file mode 100644 index 749a2481a504..000000000000 --- a/src/main/java/org/truffleruby/platform/Platform.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - ***** BEGIN LICENSE BLOCK ***** - * Version: EPL 2.0/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Eclipse Public - * License Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.eclipse.org/legal/epl-v20.html - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * Copyright (C) 2008 JRuby project - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the EPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the EPL, the GPL or the LGPL. - ***** END LICENSE BLOCK *****/ -package org.truffleruby.platform; - -import org.truffleruby.shared.BasicPlatform; - -public abstract class Platform extends BasicPlatform { - - public static final String LIB_SUFFIX = determineLibSuffix(); - public static final String CEXT_SUFFIX = OS == OS_TYPE.DARWIN ? ".bundle" : LIB_SUFFIX; - public static final boolean CEXT_SUFFIX_IS_SO = CEXT_SUFFIX.equals(".so"); - - private static String determineLibSuffix() { - switch (OS) { - case DARWIN: - return ".dylib"; - default: - return ".so"; - } - } - -} diff --git a/src/main/ruby/truffleruby/core/exception.rb b/src/main/ruby/truffleruby/core/exception.rb index 4d2cc24bcedf..e81482fd6a36 100644 --- a/src/main/ruby/truffleruby/core/exception.rb +++ b/src/main/ruby/truffleruby/core/exception.rb @@ -373,7 +373,6 @@ def initialize(message = nil, receiver: nil, key: nil) end class SignalException < Exception - alias_method :signm, :message attr_reader :signo @@ -415,22 +414,6 @@ def initialize(sig, message = undefined) @signo = signo super(name_with_prefix) end - - private def reached_top_level - if @signo == Signal::Names['VTALRM'] - warn 'not acting on top level SignalException for SIGVTALRM as it is VM reserved' - return - end - - begin - Signal.trap(@signo, 'SYSTEM_DEFAULT') - rescue ArgumentError - # some signals are reserved but we can raise them anyways - nil - end - Truffle::POSIX.raise_signal(@signo) - end - end class StopIteration diff --git a/src/main/ruby/truffleruby/core/posix.rb b/src/main/ruby/truffleruby/core/posix.rb index b6809bd5e794..5b20cfb26d19 100644 --- a/src/main/ruby/truffleruby/core/posix.rb +++ b/src/main/ruby/truffleruby/core/posix.rb @@ -264,7 +264,6 @@ def self.attach_function_eagerly(native_name, argument_types, return_type, attach_function :getpid, [], :pid_t attach_function :getppid, [], :pid_t attach_function :kill, [:pid_t, :int], :int - attach_function :raise, [:int], :int, LIBC, false, :raise_signal attach_function :getpgrp, [], :pid_t attach_function :getpgid, [:pid_t], :pid_t attach_function :setpgid, [:pid_t, :pid_t], :int diff --git a/src/shared/java/org/truffleruby/shared/BasicPlatform.java b/src/shared/java/org/truffleruby/shared/Platform.java similarity index 89% rename from src/shared/java/org/truffleruby/shared/BasicPlatform.java rename to src/shared/java/org/truffleruby/shared/Platform.java index a3e0ec35d7ca..78cbeb4a3d2c 100644 --- a/src/shared/java/org/truffleruby/shared/BasicPlatform.java +++ b/src/shared/java/org/truffleruby/shared/Platform.java @@ -37,7 +37,7 @@ import java.util.Locale; -public abstract class BasicPlatform { +public abstract class Platform { public enum OS_TYPE { LINUX("linux"), @@ -64,6 +64,10 @@ public enum ARCH { public static final OS_TYPE OS = determineOS(); public static final ARCH ARCHITECTURE = determineArchitecture(); + public static final String LIB_SUFFIX = determineLibSuffix(); + public static final String CEXT_SUFFIX = OS == OS_TYPE.DARWIN ? ".bundle" : LIB_SUFFIX; + public static final boolean CEXT_SUFFIX_IS_SO = CEXT_SUFFIX.equals(".so"); + public static String getOSName() { return OS.rubyName; } @@ -106,6 +110,15 @@ private static ARCH determineArchitecture() { } } + private static String determineLibSuffix() { + switch (OS) { + case DARWIN: + return ".dylib"; + default: + return ".so"; + } + } + public static String getKernelMajorVersion() { if (OS == OS_TYPE.DARWIN) { return BuildInformationImpl.INSTANCE.getKernelMajorVersion(); diff --git a/src/shared/java/org/truffleruby/shared/ProcessStatus.java b/src/shared/java/org/truffleruby/shared/ProcessStatus.java new file mode 100644 index 000000000000..35cf7992bd62 --- /dev/null +++ b/src/shared/java/org/truffleruby/shared/ProcessStatus.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 2.0, or + * GNU General Public License version 2, or + * GNU Lesser General Public License version 2.1. + */ +package org.truffleruby.shared; + +/** Similar to Ruby's Process::Status and waitpid(3)'s wstatus, this helper class represents either an exit code or a + * terminating signal. We encode it as a single int because this needs to be passed from the context to the launcher. */ +public abstract class ProcessStatus { + + private static final int SIGNAL_OFFSET = 1_000_000; + + public static int exitCode(int exitCode) { + // The max exit code is 255, `ruby -e 'exit -1'; echo $?` => 255. + // We modulo the exitCode to ensure there is no overlap between encoded exit codes and signal numbers. + return Integer.remainderUnsigned(exitCode, 256); + } + + public static int signal(int signo) { + return SIGNAL_OFFSET + signo; + } + + public static boolean isSignal(int processStatus) { + return processStatus > SIGNAL_OFFSET; + } + + public static int toSignal(int processStatus) { + return processStatus - SIGNAL_OFFSET; + } + +} diff --git a/src/shared/java/org/truffleruby/shared/TruffleRuby.java b/src/shared/java/org/truffleruby/shared/TruffleRuby.java index 1fbf31d2f265..9c877f63d2f0 100644 --- a/src/shared/java/org/truffleruby/shared/TruffleRuby.java +++ b/src/shared/java/org/truffleruby/shared/TruffleRuby.java @@ -42,8 +42,8 @@ public static String getVersionString(String implementationName) { LANGUAGE_VERSION, implementationName, ImageInfo.inImageCode() ? "Native" : "JVM", - BasicPlatform.getArchName(), - BasicPlatform.getOSName()); + Platform.getArchName(), + Platform.getOSName()); } public static String getEngineVersion() { diff --git a/src/main/java/org/truffleruby/signal/LibRubySignal.java b/src/signal/java/org/truffleruby/signal/LibRubySignal.java similarity index 82% rename from src/main/java/org/truffleruby/signal/LibRubySignal.java rename to src/signal/java/org/truffleruby/signal/LibRubySignal.java index 48e1b9d9ee72..b042bab92037 100644 --- a/src/main/java/org/truffleruby/signal/LibRubySignal.java +++ b/src/signal/java/org/truffleruby/signal/LibRubySignal.java @@ -9,12 +9,10 @@ */ package org.truffleruby.signal; -import org.truffleruby.platform.Platform; - public abstract class LibRubySignal { - public static void loadLibrary(String rubyHome) { - final String path = rubyHome + "/lib/cext/librubysignal" + Platform.LIB_SUFFIX; + public static void loadLibrary(String rubyHome, String libSuffix) { + final String path = rubyHome + "/lib/cext/librubysignal" + libSuffix; System.load(path); } @@ -26,4 +24,6 @@ public static void loadLibrary(String rubyHome) { public static native long getNativeThreadID(); + public static native void restoreSystemHandlerAndRaise(int signalNumber); + }