Skip to content

Commit c4e65f6

Browse files
committed
[GR-47629] Raise native signal after closing the Context for uncaught SignalException
PullRequest: truffleruby/4091
2 parents 7c5bef1 + fda3b4e commit c4e65f6

File tree

55 files changed

+217
-212
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+217
-212
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Bug fixes:
1212
* Fix `Proc#parameters` and return all the numbered parameters lower than the used explicitly ones (@andrykonchin).
1313
* Fix some C API functions which were failing when called with Ruby values represented as Java primitives (#3352, @eregon).
1414
* Fix `IO.select([io], nil, [io])` on macOS, it was hanging due to a bug in macOS `poll(2)` (#3346, @eregon, @andrykonchin).
15+
* Run context cleanup such as showing the output of tools when `SignalException` and `Interrupt` escape (@eregon).
1516

1617
Compatibility:
1718

mx.truffleruby/eclipse-settings/org.eclipse.jdt.core.prefs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
2+
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=disabled
23
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
34
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
45
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
56
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
67
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
78
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
89
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
10+
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=ignore
911
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
1012
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
1113
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false

mx.truffleruby/suite.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,22 @@
207207
"license": ["EPL-2.0"],
208208
},
209209

210-
"org.truffleruby.rubysignal": {
210+
"org.truffleruby.signal": {
211+
"dir": "src/signal",
212+
"sourceDirs": ["java"],
213+
"jniHeaders": True,
214+
"javaCompliance": "17+",
215+
"checkstyle": "org.truffleruby",
216+
"workingSets": "TruffleRuby",
217+
"license": ["EPL-2.0"],
218+
},
219+
220+
"org.truffleruby.librubysignal": {
211221
"dir": "src/main/c/rubysignal",
212222
"native": "shared_lib",
213223
"deliverable": "rubysignal",
214224
"buildDependencies": [
215-
"org.truffleruby", # for the generated JNI header file
225+
"org.truffleruby.signal", # for the generated JNI header file
216226
],
217227
"use_jdk_headers": True, # the generated JNI header includes jni.h
218228
"cflags": ["-g", "-Wall", "-Werror", "-pthread"],
@@ -245,7 +255,6 @@
245255
"org.truffleruby": {
246256
"dir": "src/main",
247257
"sourceDirs": ["java"],
248-
"jniHeaders": True,
249258
"requires": [
250259
"java.logging",
251260
"java.management",
@@ -278,6 +287,7 @@
278287
"checkstyle": "org.truffleruby",
279288
"workingSets": "TruffleRuby",
280289
"findbugsIgnoresGenerated": True,
290+
"forceJavac": True, # GR-51148 We need to force javac to silence a ECJ warning in generated code
281291
"license": [
282292
"EPL-2.0", # JRuby (we're choosing EPL out of EPL,GPL,LGPL)
283293
"BSD-new", # Rubinius
@@ -449,11 +459,13 @@
449459
"exports": [
450460
"org.truffleruby.shared to org.graalvm.ruby, org.graalvm.ruby.launcher",
451461
"org.truffleruby.shared.options to org.graalvm.ruby, org.graalvm.ruby.launcher",
462+
"org.truffleruby.signal to org.graalvm.ruby, org.graalvm.ruby.launcher",
452463
],
453464
},
454465
"useModulePath": True,
455466
"dependencies": [
456-
"org.truffleruby.shared"
467+
"org.truffleruby.shared",
468+
"org.truffleruby.signal",
457469
],
458470
"distDependencies": [
459471
"truffleruby:TRUFFLERUBY-ANNOTATIONS",
@@ -700,7 +712,7 @@
700712
"dependency:org.truffleruby.cext/src/main/c/truffleposix/<lib:truffleposix>",
701713
"dependency:org.truffleruby.cext/src/main/c/cext/<lib:truffleruby>",
702714
"dependency:org.truffleruby.cext/src/main/c/cext-trampoline/<lib:trufflerubytrampoline>",
703-
"dependency:org.truffleruby.rubysignal",
715+
"dependency:org.truffleruby.librubysignal",
704716
],
705717
# The platform-specific files from debug and rbs, see comment above
706718
"lib/gems/": "file:lib/gems/extensions",

spec/truffle/signal_exception_spec.rb

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/launcher/java/org/truffleruby/launcher/RubyLauncher.java

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,19 @@
2929
import org.graalvm.polyglot.PolyglotException;
3030
import org.graalvm.polyglot.Source;
3131
import org.graalvm.polyglot.Value;
32+
import org.truffleruby.shared.ProcessStatus;
33+
import org.truffleruby.shared.Platform;
3234
import org.truffleruby.shared.Metrics;
3335
import org.truffleruby.shared.TruffleRuby;
3436
import org.truffleruby.shared.options.OptionsCatalog;
37+
import org.truffleruby.signal.LibRubySignal;
3538

3639
public class RubyLauncher extends AbstractLanguageLauncher {
3740

3841
private CommandLineOptions config;
3942
private String implementationName = null;
4043
private boolean helpOptionUsed = false; // Any --help* option
44+
private String rubyHome = null;
4145

4246
/** NOTE: not actually used by thin launchers. The first method called with the arguments is
4347
* {@link #preprocessArguments}. */
@@ -292,30 +296,51 @@ private int runRubyMain(Context.Builder contextBuilder, CommandLineOptions confi
292296

293297
contextBuilder.arguments(TruffleRuby.LANGUAGE_ID, config.getArguments());
294298

295-
int result = runContext(contextBuilder, config);
299+
int processStatus = runContext(contextBuilder, config);
296300

297301
final boolean runTwice = config.getUnknownArguments().contains("--run-twice") ||
298302
config.getUnknownArguments().contains("--run-twice=true");
299303
if (runTwice) {
300304
final int secondResult = runContext(contextBuilder, config);
301-
if (secondResult != 0 && result == 0) {
302-
result = secondResult;
305+
if (secondResult != 0 && processStatus == 0) {
306+
processStatus = secondResult;
303307
}
304308
}
305309

306-
return result;
310+
// SignalExeption exit, we need to raise(3) the native signal to set the correct process waitpid(3) status
311+
if (ProcessStatus.isSignal(processStatus)) {
312+
int signalNumber = ProcessStatus.toSignal(processStatus);
313+
314+
if (rubyHome != null) {
315+
LibRubySignal.loadLibrary(rubyHome, Platform.LIB_SUFFIX);
316+
LibRubySignal.restoreSystemHandlerAndRaise(signalNumber);
317+
// Some signals are ignored by default, such as SIGWINCH and SIGCHLD, in that exit with 1 like CRuby
318+
return 1;
319+
} else {
320+
System.err.println("The TruffleRuby context ended with signal " + signalNumber +
321+
" but since librubysignal is not found we exit with code " + signalNumber +
322+
" instead of raising the signal");
323+
return signalNumber;
324+
}
325+
}
326+
327+
return processStatus;
307328
}
308329

309330
private int runContext(Context.Builder builder, CommandLineOptions config) {
310331
try (Context context = builder.build()) {
311332
Metrics.printTime("before-run");
312333

334+
Value rubyHome = context.eval(source(
335+
// language=ruby
336+
"Truffle::Boot.ruby_home"));
337+
if (rubyHome.isString()) {
338+
this.rubyHome = rubyHome.asString();
339+
}
340+
313341
if (config.executionAction == ExecutionAction.PATH) {
314-
final Source source = Source.newBuilder(
315-
TruffleRuby.LANGUAGE_ID,
316-
// language=ruby
317-
"-> name { Truffle::Boot.find_s_file(name) }",
318-
TruffleRuby.BOOT_SOURCE_NAME).internal(true).buildLiteral();
342+
final Source source = source(// language=ruby
343+
"-> name { Truffle::Boot.find_s_file(name) }");
319344

320345
config.executionAction = ExecutionAction.FILE;
321346
final Value file = context.eval(source).execute(config.toExecute);
@@ -329,34 +354,35 @@ private int runContext(Context.Builder builder, CommandLineOptions config) {
329354
}
330355

331356
if (config.logProcessArguments) {
332-
Value logInfo = context.eval(
333-
"ruby",
357+
Value logInfo = context.eval(source(
334358
// language=ruby
335-
"-> message { Truffle::Debug.log_info(message) }");
359+
"-> message { Truffle::Debug.log_info(message) }"));
336360
String message = "new process: truffleruby " + String.join(" ", config.initialArguments);
337361
logInfo.executeVoid(message);
338362
}
339363

340-
final Source source = Source.newBuilder(
341-
TruffleRuby.LANGUAGE_ID,
342-
// language=ruby
343-
"-> argc, argv, kind, to_execute { Truffle::Boot.main(argc, argv, kind, to_execute) }",
344-
TruffleRuby.BOOT_SOURCE_NAME).internal(true).buildLiteral();
364+
final Source source = source(// language=ruby
365+
"-> argc, argv, kind, to_execute { Truffle::Boot.main(argc, argv, kind, to_execute) }");
345366

346367
final int argc = getNativeArgc();
347368
final long argv = getNativeArgv();
348369
final String kind = config.executionAction.name();
349-
final int exitCode = context.eval(source).execute(argc, argv, kind, config.toExecute).asInt();
370+
final int processStatus = context.eval(source).execute(argc, argv, kind, config.toExecute).asInt();
350371
Metrics.printTime("after-run");
351-
return exitCode;
372+
return processStatus;
352373
} catch (PolyglotException e) {
353374
getError().println(
354375
"truffleruby: an exception escaped out of the interpreter - this is an implementation bug");
355-
e.printStackTrace();
376+
e.printStackTrace(System.err);
356377
return 1;
357378
}
358379
}
359380

381+
private static Source source(String code) {
382+
return Source.newBuilder(TruffleRuby.LANGUAGE_ID, code, TruffleRuby.BOOT_SOURCE_NAME).internal(true)
383+
.buildLiteral();
384+
}
385+
360386
private static List<String> getArgsFromEnvVariable(String name) {
361387
String value = System.getenv(name);
362388
if (value != null) {

src/main/c/rubysignal/src/rubysignal.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,16 @@ JNIEXPORT jint JNICALL Java_org_truffleruby_signal_LibRubySignal_sendSIGVTALRMTo
3737
}
3838

3939
JNIEXPORT jlong JNICALL Java_org_truffleruby_signal_LibRubySignal_getNativeThreadID(JNIEnv *env, jclass clazz) {
40-
#ifdef __APPLE__
41-
uint64_t native_id;
42-
pthread_threadid_np(NULL, &native_id);
43-
#elif defined(__linux__)
44-
pid_t native_id = (pid_t) syscall(SYS_gettid);
45-
#endif
46-
return (jlong) native_id;
40+
#ifdef __APPLE__
41+
uint64_t native_id;
42+
pthread_threadid_np(NULL, &native_id);
43+
#elif defined(__linux__)
44+
pid_t native_id = (pid_t) syscall(SYS_gettid);
45+
#endif
46+
return (jlong) native_id;
47+
}
48+
49+
JNIEXPORT void JNICALL Java_org_truffleruby_signal_LibRubySignal_restoreSystemHandlerAndRaise(JNIEnv *env, jclass clazz, jint signo) {
50+
signal(signo, SIG_DFL);
51+
raise(signo);
4752
}

src/main/java/org/truffleruby/RubyLanguage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
import org.truffleruby.parser.ParsingParameters;
117117
import org.truffleruby.parser.RubySource;
118118
import org.truffleruby.parser.TranslatorEnvironment;
119-
import org.truffleruby.platform.Platform;
119+
import org.truffleruby.shared.Platform;
120120
import org.truffleruby.shared.Metrics;
121121
import org.truffleruby.shared.TruffleRuby;
122122
import org.truffleruby.shared.options.OptionsCatalog;

src/main/java/org/truffleruby/cext/ValueWrapperManager.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,6 @@ public static final class HandleBlock {
215215

216216
@SuppressWarnings("unused") private Cleanable cleanable;
217217

218-
private HandleBlock() {
219-
base = 0;
220-
cleanable = null;
221-
wrappers = null;
222-
}
223-
224218
public HandleBlock(RubyContext context, RubyLanguage language, ValueWrapperManager manager) {
225219
HandleBlockAllocator allocator = language.handleBlockAllocator;
226220
long base = allocator.getFreeBlock();

src/main/java/org/truffleruby/collections/ConcurrentWeakSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public Object[] toArray() {
3232

3333
@TruffleBoundary
3434
public WeakSetIterator<E> iterator() {
35-
return new WeakSetIterator<E>(map.keySet().iterator());
35+
return new WeakSetIterator<>(map.keySet().iterator());
3636
}
3737

3838
private static final class WeakSetIterator<E> implements Iterator<E> {

src/main/java/org/truffleruby/core/TruffleSystemNodes.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@
6969
import org.truffleruby.language.RubyGuards;
7070
import org.truffleruby.language.control.RaiseException;
7171
import org.truffleruby.language.library.RubyStringLibrary;
72-
import org.truffleruby.platform.Platform;
73-
import org.truffleruby.shared.BasicPlatform;
72+
import org.truffleruby.shared.Platform;
7473

7574
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
7675
import com.oracle.truffle.api.TruffleFile;
@@ -214,7 +213,7 @@ public abstract static class HostCPUNode extends CoreMethodNode {
214213

215214
@Specialization
216215
RubyString hostCPU() {
217-
return createString(fromJavaStringNode, BasicPlatform.getArchName(), Encodings.UTF_8);
216+
return createString(fromJavaStringNode, Platform.getArchName(), Encodings.UTF_8);
218217
}
219218

220219
}

src/main/java/org/truffleruby/core/array/ArrayConcatNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public void doExecuteVoid(VirtualFrame frame) {
8181
}
8282
}
8383

84+
@Override
8485
public RubyNode cloneUninitialized() {
8586
var copy = new ArrayConcatNode(cloneUninitialized(children));
8687
return copy.copyFlags(this);

src/main/java/org/truffleruby/core/array/library/DoubleArrayStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static void sort(double[] store, int size) {
165165

166166
@ExportMessage
167167
static Iterable<Object> getIterable(double[] store, int from, int length) {
168-
return () -> new Iterator<Object>() {
168+
return () -> new Iterator<>() {
169169

170170
private int n = from;
171171

src/main/java/org/truffleruby/core/array/library/IntegerArrayStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static void sort(int[] store, int size) {
165165

166166
@ExportMessage
167167
static Iterable<Object> getIterable(int[] store, int from, int length) {
168-
return () -> new Iterator<Object>() {
168+
return () -> new Iterator<>() {
169169

170170
private int n = from;
171171

src/main/java/org/truffleruby/core/array/library/LongArrayStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static void sort(long[] store, int size) {
186186

187187
@ExportMessage
188188
static Iterable<Object> getIterable(long[] store, int from, int length) {
189-
return () -> new Iterator<Object>() {
189+
return () -> new Iterator<>() {
190190

191191
private int n = from;
192192

src/main/java/org/truffleruby/core/array/library/NativeArrayStorage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ protected Object[] toJavaArrayCopy(int size,
221221
@ExportMessage
222222
static Iterable<Object> getIterable(NativeArrayStorage store, int from, int length,
223223
@CachedLibrary("store") ArrayStoreLibrary stores) {
224-
return () -> new Iterator<Object>() {
224+
return () -> new Iterator<>() {
225225

226226
private int n = from;
227227

src/main/java/org/truffleruby/core/array/library/ObjectArrayStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ static Object[] toJavaArrayCopy(Object[] store, int length) {
160160

161161
@ExportMessage
162162
static Iterable<Object> getIterable(Object[] store, int from, int length) {
163-
return () -> new Iterator<Object>() {
163+
return () -> new Iterator<>() {
164164

165165
private int n = from;
166166

src/main/java/org/truffleruby/core/fiber/FiberManager.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,10 +478,6 @@ public RubyFiber getSendingFiber() {
478478
return sendingFiber;
479479
}
480480

481-
public ArgumentsDescriptor getDescriptor() {
482-
return descriptor;
483-
}
484-
485481
public Object[] getArgs() {
486482
return args;
487483
}

src/main/java/org/truffleruby/core/format/rbsprintf/RBSprintfCompiler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public RootCallTarget compile(AbstractTruffleString formatTString, RubyEncoding
4242
Object stringReader) {
4343
var byteArray = formatTString.getInternalByteArrayUncached(formatEncoding.tencoding);
4444

45-
final RBSprintfSimpleParser parser = new RBSprintfSimpleParser(StringSupport.bytesToChars(byteArray), false);
45+
final RBSprintfSimpleParser parser = new RBSprintfSimpleParser(StringSupport.bytesToChars(byteArray));
4646
final List<RBSprintfConfig> configs = parser.parse();
4747
final RBSprintfSimpleTreeBuilder builder = new RBSprintfSimpleTreeBuilder(configs, stringReader,
4848
formatEncoding);
@@ -60,7 +60,7 @@ public RubyArray typeList(AbstractTruffleString formatTString, RubyEncoding form
6060
TruffleString.GetInternalByteArrayNode byteArrayNode, RubyContext context, RubyLanguage language) {
6161
var byteArray = byteArrayNode.execute(formatTString, formatEncoding.tencoding);
6262

63-
final RBSprintfSimpleParser parser = new RBSprintfSimpleParser(StringSupport.bytesToChars(byteArray), false);
63+
final RBSprintfSimpleParser parser = new RBSprintfSimpleParser(StringSupport.bytesToChars(byteArray));
6464
final List<RBSprintfConfig> configs = parser.parse();
6565
final int[] types = new int[3 * configs.size()]; // Ensure there is enough space for the argument types that might be in the format string.
6666

0 commit comments

Comments
 (0)