Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jcouball opened this issue Apr 1, 2025 · 3 comments
Open

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

jcouball opened this issue Apr 1, 2025 · 3 comments
Assignees

Comments

@jcouball
Copy link
Contributor

jcouball commented Apr 1, 2025

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!

@andrykonchin
Copy link
Member

Thank you for the report, we'll look into it.

@andrykonchin andrykonchin self-assigned this Apr 2, 2025
@jcouball
Copy link
Contributor Author

jcouball commented Apr 2, 2025

Thank you @andrykonchin!

Upon reviewing my initial report, I believe I overlooked the possibility of additional errors that could occur and trigger a CRuby exception.

Generally, if there is an issue that prevents Ruby from executing the subprocess, it should raise an error. Returning a Process::Status should be reserved for reporting on the outcomes of the subprocess’s execution.

@eregon
Copy link
Member

eregon commented May 5, 2025

We use posix_spawnp() which might not always tell us that difference.
Similar issue when Process.spawn uses the shell, and this also happens on CRuby.

But for the chdir case reported here we can easily check it in the calling process with Dir.exist? so this should be an easy fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants