Skip to content

Commit 2cab36b

Browse files
committed
Add --log-subprocess for debugging
1 parent 5a22015 commit 2cab36b

File tree

8 files changed

+72
-12
lines changed

8 files changed

+72
-12
lines changed

doc/contributor/debugging.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ You've got many options for debugging the implementation of TruffleRuby.
55
If you want to debug an application running on TruffleRuby, and don't suspect
66
any bug in TruffleRuby itself, use GraalVM [tools](../user/tools.md) as usual.
77

8+
Also see [user debugging docs](../user/debugging.md).
9+
810
## Print Debugging
911

1012
`System.err.println(...);` in Java and `p` in Ruby is a great first tool to use for

doc/user/debugging.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,12 @@ When debugging you may want to see this information.
4040
An option to show more information is `--backtraces-interleave-java=true`, which shows you the Java methods involved in executing each Ruby method.
4141

4242
When you are interoperating with other languages, including C extensions, backtraces for Java exceptions may be missing information, as the Java frames are gone by the time Ruby has a chance to format them into a backtrace.
43+
44+
## Printing Subprocesses
45+
46+
You can print all subprocesses created by TruffleRuby using the option `--log-subprocess`.
47+
48+
```bash
49+
$ ruby --log-subprocess -e '`ls .`'
50+
[ruby] INFO: spawn: ls .
51+
```

src/main/java/org/truffleruby/debug/TruffleDebugNodes.java

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -330,36 +330,53 @@ protected int getCacheLimit() {
330330

331331
}
332332

333-
@CoreMethod(names = "log_config", onSingleton = true, required = 1)
334-
public abstract static class LogConfigNode extends CoreMethodArrayArgumentsNode {
333+
@CoreMethod(names = "log_warning", onSingleton = true, required = 1)
334+
public abstract static class LogWarningNode extends CoreMethodArrayArgumentsNode {
335335

336336
@Specialization
337-
protected Object logConfig(Object value,
337+
protected Object logWarning(Object value,
338+
@Cached ToJavaStringNode toJavaStringNode) {
339+
warning(toJavaStringNode.executeToJavaString(value));
340+
return nil;
341+
}
342+
343+
@TruffleBoundary
344+
static void warning(String message) {
345+
RubyLanguage.LOGGER.warning(message);
346+
}
347+
348+
}
349+
350+
@CoreMethod(names = "log_info", onSingleton = true, required = 1)
351+
public abstract static class LogInfoNode extends CoreMethodArrayArgumentsNode {
352+
353+
@Specialization
354+
protected Object logInfo(Object value,
338355
@Cached ToJavaStringNode toJavaStringNode) {
339356
config(toJavaStringNode.executeToJavaString(value));
340357
return nil;
341358
}
342359

343360
@TruffleBoundary
344361
static void config(String message) {
345-
RubyLanguage.LOGGER.config(message);
362+
RubyLanguage.LOGGER.info(message);
346363
}
347364

348365
}
349366

350-
@CoreMethod(names = "log_warning", onSingleton = true, required = 1)
351-
public abstract static class LogWarningNode extends CoreMethodArrayArgumentsNode {
367+
@CoreMethod(names = "log_config", onSingleton = true, required = 1)
368+
public abstract static class LogConfigNode extends CoreMethodArrayArgumentsNode {
352369

353370
@Specialization
354-
protected Object logWarning(Object value,
371+
protected Object logConfig(Object value,
355372
@Cached ToJavaStringNode toJavaStringNode) {
356-
warning(toJavaStringNode.executeToJavaString(value));
373+
config(toJavaStringNode.executeToJavaString(value));
357374
return nil;
358375
}
359376

360377
@TruffleBoundary
361-
static void warning(String message) {
362-
RubyLanguage.LOGGER.warning(message);
378+
static void config(String message) {
379+
RubyLanguage.LOGGER.config(message);
363380
}
364381

365382
}

src/main/java/org/truffleruby/language/TruffleBootNodes.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,8 @@ protected Object getOption(Object optionName,
319319
if (descriptor == null) {
320320
throw new RaiseException(
321321
getContext(),
322-
coreExceptions().nameError("option not defined", nil, optionNameString, this));
322+
coreExceptions()
323+
.nameError("option not defined: " + optionNameString, nil, optionNameString, this));
323324
}
324325

325326
Object value = getContext().getOptions().fromDescriptor(descriptor);

src/main/java/org/truffleruby/options/Options.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public class Options {
7171
public final boolean HASHING_DETERMINISTIC;
7272
/** --fiber-leave-context=true */
7373
public final boolean FIBER_LEAVE_CONTEXT;
74+
/** --log-subprocess=false */
75+
public final boolean LOG_SUBPROCESS;
7476
/** --exceptions-store-java=false */
7577
public final boolean EXCEPTIONS_STORE_JAVA;
7678
/** --exceptions-print-java=false */
@@ -215,6 +217,7 @@ public Options(Env env, OptionValues options, LanguageOptions languageOptions) {
215217
PATCHING = options.get(OptionsCatalog.PATCHING_KEY);
216218
HASHING_DETERMINISTIC = options.get(OptionsCatalog.HASHING_DETERMINISTIC_KEY);
217219
FIBER_LEAVE_CONTEXT = options.get(OptionsCatalog.FIBER_LEAVE_CONTEXT_KEY);
220+
LOG_SUBPROCESS = options.get(OptionsCatalog.LOG_SUBPROCESS_KEY);
218221
EXCEPTIONS_STORE_JAVA = options.get(OptionsCatalog.EXCEPTIONS_STORE_JAVA_KEY);
219222
EXCEPTIONS_PRINT_JAVA = options.get(OptionsCatalog.EXCEPTIONS_PRINT_JAVA_KEY);
220223
EXCEPTIONS_PRINT_UNCAUGHT_JAVA = options.get(OptionsCatalog.EXCEPTIONS_PRINT_UNCAUGHT_JAVA_KEY);
@@ -326,6 +329,8 @@ public Object fromDescriptor(OptionDescriptor descriptor) {
326329
return HASHING_DETERMINISTIC;
327330
case "ruby.fiber-leave-context":
328331
return FIBER_LEAVE_CONTEXT;
332+
case "ruby.log-subprocess":
333+
return LOG_SUBPROCESS;
329334
case "ruby.exceptions-store-java":
330335
return EXCEPTIONS_STORE_JAVA;
331336
case "ruby.exceptions-print-java":

src/main/ruby/truffleruby/core/truffle/process_operations.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ def convert_env_value(value)
350350

351351
def spawn_setup(alter_process)
352352
env = @options.delete(:unsetenv_others) ? {} : ENV.to_hash
353-
if add_to_env = @options.delete(:env)
353+
@add_to_env = add_to_env = @options.delete(:env)
354+
if add_to_env
354355
add_to_env.each do |key, value|
355356
if value
356357
env[key] = value
@@ -415,6 +416,7 @@ def redirect_file_descriptor(from, to, alter_process)
415416
end
416417

417418
def spawn
419+
log_command 'spawn'
418420
pid = posix_spawnp @command, @argv, @env_array, @options
419421
# Check if the command exists *after* invoking posix_spawn so we have a pid
420422
if not resolve_in_path(@command)
@@ -497,6 +499,7 @@ def posix_spawnp(command, args, env_array, options)
497499
end
498500

499501
def exec
502+
log_command('exec')
500503
# exec validates the command only if it searches in $PATH
501504
if should_search_path?(@command)
502505
if resolved = resolve_in_path(@command)
@@ -516,6 +519,17 @@ def exec
516519
raise SystemCallError.new('execve() should not return', 0)
517520
end
518521

522+
Truffle::Boot.delay do
523+
LOG_SUBPROCESS = Truffle::Boot.get_option 'log-subprocess'
524+
end
525+
526+
def log_command(type)
527+
if LOG_SUBPROCESS
528+
env = (@add_to_env || {}).map { |k,v| "#{k}=#{v}" }.join(' ')
529+
Truffle::Debug.log_info "#{type}: #{env}#{' ' unless env.empty?}#{@argv.join(' ')}"
530+
end
531+
end
532+
519533
def should_use_shell?(command)
520534
command.b.match?(SHELL_META_CHAR_PATTERN)
521535
end

src/options.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ EXPERT:
101101
PATCHING: [patching, boolean, true, Use patching]
102102
HASHING_DETERMINISTIC: [hashing-deterministic, boolean, false, Produce deterministic hash values]
103103
FIBER_LEAVE_CONTEXT: [fiber-leave-context, boolean, true, 'Leave the TruffleContext when suspending a Fiber (avoids triggering multithreading)']
104+
LOG_SUBPROCESS: [log-subprocess, boolean, false, 'Log whenever a subprocess is created']
104105

105106
# Options to tweak backtraces
106107
EXCEPTIONS_STORE_JAVA: [exceptions-store-java, boolean, false, Store the Java exception with the Ruby backtrace]

src/shared/java/org/truffleruby/shared/options/OptionsCatalog.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public class OptionsCatalog {
5353
public static final OptionKey<Boolean> PATCHING_KEY = new OptionKey<>(true);
5454
public static final OptionKey<Boolean> HASHING_DETERMINISTIC_KEY = new OptionKey<>(false);
5555
public static final OptionKey<Boolean> FIBER_LEAVE_CONTEXT_KEY = new OptionKey<>(true);
56+
public static final OptionKey<Boolean> LOG_SUBPROCESS_KEY = new OptionKey<>(false);
5657
public static final OptionKey<Boolean> EXCEPTIONS_STORE_JAVA_KEY = new OptionKey<>(false);
5758
public static final OptionKey<Boolean> EXCEPTIONS_PRINT_JAVA_KEY = new OptionKey<>(false);
5859
public static final OptionKey<Boolean> EXCEPTIONS_PRINT_UNCAUGHT_JAVA_KEY = new OptionKey<>(false);
@@ -385,6 +386,13 @@ public class OptionsCatalog {
385386
.stability(OptionStability.EXPERIMENTAL)
386387
.build();
387388

389+
public static final OptionDescriptor LOG_SUBPROCESS = OptionDescriptor
390+
.newBuilder(LOG_SUBPROCESS_KEY, "ruby.log-subprocess")
391+
.help("Log whenever a subprocess is created")
392+
.category(OptionCategory.EXPERT)
393+
.stability(OptionStability.EXPERIMENTAL)
394+
.build();
395+
388396
public static final OptionDescriptor EXCEPTIONS_STORE_JAVA = OptionDescriptor
389397
.newBuilder(EXCEPTIONS_STORE_JAVA_KEY, "ruby.exceptions-store-java")
390398
.help("Store the Java exception with the Ruby backtrace")
@@ -1153,6 +1161,8 @@ public static OptionDescriptor fromName(String name) {
11531161
return HASHING_DETERMINISTIC;
11541162
case "ruby.fiber-leave-context":
11551163
return FIBER_LEAVE_CONTEXT;
1164+
case "ruby.log-subprocess":
1165+
return LOG_SUBPROCESS;
11561166
case "ruby.exceptions-store-java":
11571167
return EXCEPTIONS_STORE_JAVA;
11581168
case "ruby.exceptions-print-java":
@@ -1393,6 +1403,7 @@ public static OptionDescriptor[] allDescriptors() {
13931403
PATCHING,
13941404
HASHING_DETERMINISTIC,
13951405
FIBER_LEAVE_CONTEXT,
1406+
LOG_SUBPROCESS,
13961407
EXCEPTIONS_STORE_JAVA,
13971408
EXCEPTIONS_PRINT_JAVA,
13981409
EXCEPTIONS_PRINT_UNCAUGHT_JAVA,

0 commit comments

Comments
 (0)