Class: RailVerdict::ProcessRunner
- Inherits:
-
Object
- Object
- RailVerdict::ProcessRunner
- Defined in:
- lib/rail_verdict/process_runner.rb
Defined Under Namespace
Classes: DirectoryError, Registry, RunResult
Constant Summary collapse
- DEFAULT_TIMEOUT_SECONDS =
30.0- DEFAULT_MAX_STDOUT_BYTES =
4 * 1024 * 1024
- DEFAULT_MAX_STDERR_BYTES =
64 * 1024
- MAX_SAFE_STDOUT_BYTES =
Safe ceiling prevents configuration from escalating to unbounded memory.
64 * 1024 * 1024
- MAX_SAFE_STDERR_BYTES =
1 * 1024 * 1024
- RSPEC_MAX_STDOUT_BYTES =
16 * 1024 * 1024
- READ_CHUNK_BYTES =
64 * 1024
- TERM_GRACE_SECONDS =
0.1- REAP_POLL_SECONDS =
0.01- ENV_ALLOWLIST =
%w[ PATH HOME GEM_HOME GEM_PATH LANG RAILVERDICT_MINITEST_OUTPUT ].freeze
- FORCED_ENV =
{ "LC_ALL" => "C.UTF-8", "TZ" => "UTC" }.freeze
Class Method Summary collapse
- .build_env ⇒ Object
- .registry ⇒ Object
- .run(executable, argv, chdir:, timeout_seconds: DEFAULT_TIMEOUT_SECONDS, max_stdout_bytes: DEFAULT_MAX_STDOUT_BYTES, max_stderr_bytes: DEFAULT_MAX_STDERR_BYTES, binary_output: false) ⇒ Object
Class Method Details
.build_env ⇒ Object
74 75 76 77 78 79 80 81 |
# File 'lib/rail_verdict/process_runner.rb', line 74 def build_env env = ENV.keys.to_h { |key| [key, nil] } ENV_ALLOWLIST.each do |key| value = ENV[key] env[key] = value unless value.nil? end env.merge(FORCED_ENV) end |
.registry ⇒ Object
70 71 72 |
# File 'lib/rail_verdict/process_runner.rb', line 70 def registry @registry ||= Registry.new end |
.run(executable, argv, chdir:, timeout_seconds: DEFAULT_TIMEOUT_SECONDS, max_stdout_bytes: DEFAULT_MAX_STDOUT_BYTES, max_stderr_bytes: DEFAULT_MAX_STDERR_BYTES, binary_output: false) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/rail_verdict/process_runner.rb', line 30 def run(executable, argv, chdir:, timeout_seconds: DEFAULT_TIMEOUT_SECONDS, max_stdout_bytes: DEFAULT_MAX_STDOUT_BYTES, max_stderr_bytes: DEFAULT_MAX_STDERR_BYTES, binary_output: false) max_stdout_bytes = clamp_limit(max_stdout_bytes, DEFAULT_MAX_STDOUT_BYTES, MAX_SAFE_STDOUT_BYTES) max_stderr_bytes = clamp_limit(max_stderr_bytes, DEFAULT_MAX_STDERR_BYTES, MAX_SAFE_STDERR_BYTES) directory = verify_directory(chdir) argv = argv.map { |element| validate_argv_element(element) } env = build_env stdout_read, stdout_write = IO.pipe stderr_read, stderr_write = IO.pipe pid = nil begin pid = Process.spawn( env, [executable, File.basename(executable)], *argv, chdir: directory, pgroup: true, in: :close, out: stdout_write, err: stderr_write ) rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, ArgumentError => error return spawn_failure_result(error) end registry.register(pid) stdout_write.close stderr_write.close execute_child(pid, stdout_read, stderr_read, timeout_seconds, max_stdout_bytes, max_stderr_bytes, binary_output) ensure registry.unregister(pid) if pid [stdout_read, stdout_write, stderr_read, stderr_write].compact.each do |io| io.close unless io.closed? end end |