Skip to content

Process.spawn does not raise an error when expected in TruffleRuby #3825

Open
@jcouball

Description

@jcouball

In CRuby, when Process.spawn is given an invalid chdir: option (pointing to a nonexistent directory), it raises an Errno::ENOENT error. However, in TruffleRuby, Process.spawn does not raise an error. Instead, it returns a Process::Status object with exitstatus == 1.

This behavior creates ambiguity—it’s unclear whether the subprocess failed to start or if it started and exited with a failure code.

Expected Behavior (CRuby 3.4.1)

When Process.spawn is called with a nonexistent chdir: directory, it should raise an error:

$ ruby --version
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24]
$ irb
irb(main):001> Process.wait2(Process.spawn('pwd', chdir: 'does_not_exist'))
(irb):1:in 'Process.spawn': No such file or directory - does_not_exist (Errno::ENOENT)

Actual Behavior (TruffleRuby 24.1.2)

Instead of raising an error, TruffleRuby prints an error message but returns a Process::Status object:

$ ruby --version
truffleruby 24.1.2, like ruby 3.2.4, Oracle GraalVM Native [arm64-darwin20]
$ irb
irb(main):001:0> Process.wait2(Process.spawn('pwd', chdir: 'does_not_exist'))
chdir: No such file or directory
working_directory=does_not_exist
=> [69902, #<Process::Status: pid 69902 exit 1>]

Why This is a Problem

  1. Inconsistent with CRuby Behavior: TruffleRuby’s behavior deviates from the standard Ruby implementation.
  2. Ambiguous Error Handling: When Process::Status has exitstatus == 1, there’s no clear way to distinguish between:
    • A subprocess that failed to start (e.g., due to an invalid chdir:).
    • A subprocess that started but exited with failure.
  3. Cross-Ruby Compatibility: I maintain a Ruby gem that calls Process.spawn, and this difference in behavior makes it difficult to ensure consistent error handling across Ruby implementations.

Questions for the TruffleRuby Team

  • Is this behavior intentional?
  • If so, how should developers differentiate between a process that couldn’t start vs. one that started and failed?
  • Would it be possible to align TruffleRuby with CRuby by raising Errno::ENOENT in this case?

Thanks for your time and consideration!

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions