childprocess 4.1.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +32 -0
  3. data/CHANGELOG.md +10 -0
  4. data/Gemfile +3 -2
  5. data/README.md +5 -23
  6. data/childprocess.gemspec +2 -0
  7. data/lib/childprocess/abstract_process.rb +1 -1
  8. data/lib/childprocess/errors.rb +0 -21
  9. data/lib/childprocess/process_spawn_process.rb +127 -0
  10. data/lib/childprocess/unix/process.rb +3 -64
  11. data/lib/childprocess/unix.rb +2 -4
  12. data/lib/childprocess/version.rb +1 -1
  13. data/lib/childprocess/windows/process.rb +13 -116
  14. data/lib/childprocess/windows.rb +0 -29
  15. data/lib/childprocess.rb +16 -53
  16. data/spec/childprocess_spec.rb +39 -15
  17. data/spec/io_spec.rb +1 -1
  18. data/spec/spec_helper.rb +5 -20
  19. data/spec/unix_spec.rb +3 -7
  20. metadata +19 -24
  21. data/.travis.yml +0 -37
  22. data/appveyor.yml +0 -36
  23. data/lib/childprocess/jruby/io.rb +0 -16
  24. data/lib/childprocess/jruby/process.rb +0 -184
  25. data/lib/childprocess/jruby/pump.rb +0 -53
  26. data/lib/childprocess/jruby.rb +0 -56
  27. data/lib/childprocess/tools/generator.rb +0 -146
  28. data/lib/childprocess/unix/fork_exec_process.rb +0 -78
  29. data/lib/childprocess/unix/lib.rb +0 -186
  30. data/lib/childprocess/unix/platform/arm64-macosx.rb +0 -11
  31. data/lib/childprocess/unix/platform/i386-linux.rb +0 -12
  32. data/lib/childprocess/unix/platform/i386-solaris.rb +0 -11
  33. data/lib/childprocess/unix/platform/x86_64-linux.rb +0 -12
  34. data/lib/childprocess/unix/platform/x86_64-macosx.rb +0 -11
  35. data/lib/childprocess/unix/posix_spawn_process.rb +0 -134
  36. data/lib/childprocess/windows/handle.rb +0 -91
  37. data/lib/childprocess/windows/lib.rb +0 -416
  38. data/lib/childprocess/windows/process_builder.rb +0 -178
  39. data/lib/childprocess/windows/structs.rb +0 -149
  40. data/spec/jruby_spec.rb +0 -24
data/lib/childprocess.rb CHANGED
@@ -2,6 +2,7 @@ require 'childprocess/version'
2
2
  require 'childprocess/errors'
3
3
  require 'childprocess/abstract_process'
4
4
  require 'childprocess/abstract_io'
5
+ require 'childprocess/process_spawn_process'
5
6
  require "fcntl"
6
7
  require 'logger'
7
8
 
@@ -15,15 +16,9 @@ module ChildProcess
15
16
  def new(*args)
16
17
  case os
17
18
  when :macosx, :linux, :solaris, :bsd, :cygwin, :aix
18
- if posix_spawn?
19
- Unix::PosixSpawnProcess.new(args)
20
- elsif jruby?
21
- JRuby::Process.new(args)
22
- else
23
- Unix::ForkExecProcess.new(args)
24
- end
19
+ Unix::Process.new(*args)
25
20
  when :windows
26
- Windows::Process.new(args)
21
+ Windows::Process.new(*args)
27
22
  else
28
23
  raise Error, "unsupported platform #{platform_name.inspect}"
29
24
  end
@@ -40,13 +35,7 @@ module ChildProcess
40
35
  end
41
36
 
42
37
  def platform
43
- if RUBY_PLATFORM == "java"
44
- :jruby
45
- elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == "ironruby"
46
- :ironruby
47
- else
48
- os
49
- end
38
+ os
50
39
  end
51
40
 
52
41
  def platform_name
@@ -62,35 +51,18 @@ module ChildProcess
62
51
  end
63
52
 
64
53
  def jruby?
65
- platform == :jruby
54
+ RUBY_ENGINE == 'jruby'
66
55
  end
67
56
 
68
57
  def windows?
69
58
  os == :windows
70
59
  end
71
60
 
72
- def posix_spawn?
73
- enabled = @posix_spawn || %w[1 true].include?(ENV['CHILDPROCESS_POSIX_SPAWN'])
74
- return false unless enabled
75
-
76
- begin
77
- require 'ffi'
78
- rescue LoadError
79
- raise ChildProcess::MissingFFIError
80
- end
81
-
82
- begin
83
- require "childprocess/unix/platform/#{ChildProcess.platform_name}"
84
- rescue LoadError
85
- raise ChildProcess::MissingPlatformError
86
- end
87
-
88
- require "childprocess/unix/lib"
89
- require 'childprocess/unix/posix_spawn_process'
61
+ def posix_spawn_chosen_explicitly?
62
+ @posix_spawn || %w[1 true].include?(ENV['CHILDPROCESS_POSIX_SPAWN'])
63
+ end
90
64
 
91
- true
92
- rescue ChildProcess::MissingPlatformError => ex
93
- warn_once ex.message
65
+ def posix_spawn?
94
66
  false
95
67
  end
96
68
 
@@ -103,6 +75,8 @@ module ChildProcess
103
75
  end
104
76
 
105
77
  def os
78
+ return :windows if ENV['FAKE_WINDOWS'] == 'true'
79
+
106
80
  @os ||= (
107
81
  require "rbconfig"
108
82
  host_os = RbConfig::CONFIG['host_os'].downcase
@@ -158,17 +132,6 @@ module ChildProcess
158
132
  def close_on_exec(file)
159
133
  if file.respond_to?(:close_on_exec=)
160
134
  file.close_on_exec = true
161
- elsif file.respond_to?(:fcntl) && defined?(Fcntl::FD_CLOEXEC)
162
- file.fcntl Fcntl::F_SETFD, Fcntl::FD_CLOEXEC
163
-
164
- if jruby? && posix_spawn?
165
- # on JRuby, the fcntl call above apparently isn't enough when
166
- # we're launching the process through posix_spawn.
167
- fileno = JRuby.posix_fileno_for(file)
168
- Unix::Lib.fcntl fileno, Fcntl::F_SETFD, Fcntl::FD_CLOEXEC
169
- end
170
- elsif windows?
171
- Windows::Lib.dont_inherit file
172
135
  else
173
136
  raise Error, "not sure how to set close-on-exec for #{file.inspect} on #{platform_name.inspect}"
174
137
  end
@@ -203,8 +166,8 @@ module ChildProcess
203
166
  end # class << self
204
167
  end # ChildProcess
205
168
 
206
- require 'jruby' if ChildProcess.jruby?
207
-
208
- require 'childprocess/unix' if ChildProcess.unix?
209
- require 'childprocess/windows' if ChildProcess.windows?
210
- require 'childprocess/jruby' if ChildProcess.jruby?
169
+ if ChildProcess.windows?
170
+ require 'childprocess/windows'
171
+ else
172
+ require 'childprocess/unix'
173
+ end
@@ -1,7 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require File.expand_path('../spec_helper', __FILE__)
4
- require 'rubygems/mock_gem_ui'
5
4
 
6
5
 
7
6
  describe ChildProcess do
@@ -11,12 +10,17 @@ describe ChildProcess do
11
10
  let(:gemspec) { eval(File.read "#{here}/../childprocess.gemspec") }
12
11
 
13
12
  it 'validates cleanly' do
14
- mock_ui = Gem::MockGemUi.new
15
- Gem::DefaultUserInteraction.use_ui(mock_ui) { gemspec.validate }
13
+ if Gem::VERSION >= "3.5.0"
14
+ expect { gemspec.validate }.not_to output(/warn/i).to_stderr
15
+ else
16
+ require 'rubygems/mock_gem_ui'
16
17
 
17
- expect(mock_ui.error).to_not match(/warn/i)
18
- end
18
+ mock_ui = Gem::MockGemUi.new
19
+ Gem::DefaultUserInteraction.use_ui(mock_ui) { gemspec.validate }
19
20
 
21
+ expect(mock_ui.error).to_not match(/warn/i)
22
+ end
23
+ end
20
24
 
21
25
  it "returns self when started" do
22
26
  process = sleeping_ruby
@@ -25,14 +29,7 @@ describe ChildProcess do
25
29
  expect(process).to be_alive
26
30
  end
27
31
 
28
- # We can't detect failure to execve() when using posix_spawn() on Linux
29
- # without waiting for the child to exit with code 127.
30
- #
31
- # See e.g. http://repo.or.cz/w/glibc.git/blob/669704fd:/sysdeps/posix/spawni.c#l34
32
- #
33
- # We could work around this by doing the PATH search ourselves, but not sure
34
- # it's worth it.
35
- it "raises ChildProcess::LaunchError if the process can't be started", :posix_spawn_on_linux => false do
32
+ it "raises ChildProcess::LaunchError if the process can't be started" do
36
33
  expect { invalid_process.start }.to raise_error(ChildProcess::LaunchError)
37
34
  end
38
35
 
@@ -95,7 +92,7 @@ describe ChildProcess do
95
92
  end
96
93
  end
97
94
 
98
- it "can override env vars only for the current process" do
95
+ it "can override env vars only for the child process" do
99
96
  Tempfile.open("env-spec") do |file|
100
97
  file.close
101
98
  process = write_env(file.path)
@@ -127,6 +124,31 @@ describe ChildProcess do
127
124
  end
128
125
  end
129
126
 
127
+ it "can set env vars using Symbol keys and values" do
128
+ Tempfile.open("env-spec") do |file|
129
+ process = ruby('puts ENV["SYMBOL_KEY"]')
130
+ process.environment[:SYMBOL_KEY] = :VALUE
131
+ process.io.stdout = file
132
+ process.start
133
+ process.wait
134
+ expect(rewind_and_read(file)).to eq "VALUE\n"
135
+ end
136
+ end
137
+
138
+ it "raises ChildProcess::InvalidEnvironmentVariable for invalid env vars" do
139
+ process = ruby(':OK')
140
+ process.environment["a\0b"] = '1'
141
+ expect { process.start }.to raise_error(ChildProcess::InvalidEnvironmentVariable)
142
+
143
+ process = ruby(':OK')
144
+ process.environment["A=1"] = '2'
145
+ expect { process.start }.to raise_error(ChildProcess::InvalidEnvironmentVariable)
146
+
147
+ process = ruby(':OK')
148
+ process.environment['A'] = "a\0b"
149
+ expect { process.start }.to raise_error(ChildProcess::InvalidEnvironmentVariable)
150
+ end
151
+
130
152
  it "inherits the parent's env vars also when some are overridden" do
131
153
  Tempfile.open("env-spec") do |file|
132
154
  file.close
@@ -277,7 +299,7 @@ describe ChildProcess do
277
299
  }
278
300
  end
279
301
 
280
- it 'kills the full process tree', :process_builder => false do
302
+ it 'kills the full process tree' do
281
303
  Tempfile.open('kill-process-tree') do |file|
282
304
  process = write_pid_in_sleepy_grand_child(file.path)
283
305
  process.leader = true
@@ -288,6 +310,8 @@ describe ChildProcess do
288
310
  end
289
311
 
290
312
  process.stop
313
+ expect(process).to be_exited
314
+
291
315
  wait_until(3) { expect(alive?(pid)).to eql(false) }
292
316
  end
293
317
  end
data/spec/io_spec.rb CHANGED
@@ -151,7 +151,7 @@ describe ChildProcess do
151
151
  # http://travis-ci.org/#!/enkessler/childprocess/jobs/487331
152
152
  #
153
153
 
154
- it "works with pipes", :process_builder => false do
154
+ it "works with pipes" do
155
155
  process = ruby(<<-CODE)
156
156
  STDOUT.print "stdout"
157
157
  STDERR.print "stderr"
data/spec/spec_helper.rb CHANGED
@@ -11,10 +11,10 @@ require 'rspec'
11
11
  require 'tempfile'
12
12
  require 'socket'
13
13
  require 'stringio'
14
- require 'ostruct'
15
14
 
16
15
  module ChildProcessSpecHelper
17
16
  RUBY = defined?(Gem) ? Gem.ruby : 'ruby'
17
+ CapturedOutput = Struct.new(:stdout, :stderr)
18
18
 
19
19
  def ruby_process(*args)
20
20
  @process = ChildProcess.build(RUBY , *args)
@@ -210,16 +210,9 @@ module ChildProcessSpecHelper
210
210
  end
211
211
 
212
212
  def alive?(pid)
213
- if ChildProcess.windows?
214
- ChildProcess::Windows::Lib.alive?(pid)
215
- else
216
- begin
217
- Process.getpgid pid
218
- true
219
- rescue Errno::ESRCH
220
- false
221
- end
222
- end
213
+ !!Process.kill(0, pid)
214
+ rescue Errno::ESRCH
215
+ false
223
216
  end
224
217
 
225
218
  def capture_std
@@ -236,7 +229,7 @@ module ChildProcessSpecHelper
236
229
 
237
230
  yield
238
231
 
239
- OpenStruct.new stdout: rewind_and_read(out), stderr: rewind_and_read(err)
232
+ CapturedOutput.new rewind_and_read(out), rewind_and_read(err)
240
233
  ensure
241
234
  STDOUT.reopen orig_out
242
235
  STDERR.reopen orig_err
@@ -259,12 +252,4 @@ RSpec.configure do |c|
259
252
  c.after(:each) {
260
253
  defined?(@process) && @process.alive? && @process.stop
261
254
  }
262
-
263
- if ChildProcess.jruby? && ChildProcess.new("true").instance_of?(ChildProcess::JRuby::Process)
264
- c.filter_run_excluding :process_builder => false
265
- end
266
-
267
- if ChildProcess.linux? && ChildProcess.posix_spawn?
268
- c.filter_run_excluding :posix_spawn_on_linux => false
269
- end
270
255
  end
data/spec/unix_spec.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
  require "pid_behavior"
3
3
 
4
- if ChildProcess.unix? && !ChildProcess.jruby? && !ChildProcess.posix_spawn?
4
+ if ChildProcess.unix?
5
5
 
6
6
  describe ChildProcess::Unix::Process do
7
7
  it_behaves_like "a platform that provides the child's pid"
@@ -9,7 +9,7 @@ if ChildProcess.unix? && !ChildProcess.jruby? && !ChildProcess.posix_spawn?
9
9
  it "handles ECHILD race condition where process dies between timeout and KILL" do
10
10
  process = sleeping_ruby
11
11
 
12
- allow(process).to receive(:fork).and_return('fakepid')
12
+ allow(Process).to receive(:spawn).and_return('fakepid')
13
13
  allow(process).to receive(:send_term)
14
14
  allow(process).to receive(:poll_for_exit).and_raise(ChildProcess::TimeoutError)
15
15
  allow(process).to receive(:send_kill).and_raise(Errno::ECHILD.new)
@@ -18,14 +18,12 @@ if ChildProcess.unix? && !ChildProcess.jruby? && !ChildProcess.posix_spawn?
18
18
  expect { process.stop }.not_to raise_error
19
19
 
20
20
  allow(process).to receive(:alive?).and_return(false)
21
-
22
- process.send(:send_signal, 'TERM')
23
21
  end
24
22
 
25
23
  it "handles ESRCH race condition where process dies between timeout and KILL" do
26
24
  process = sleeping_ruby
27
25
 
28
- allow(process).to receive(:fork).and_return('fakepid')
26
+ allow(Process).to receive(:spawn).and_return('fakepid')
29
27
  allow(process).to receive(:send_term)
30
28
  allow(process).to receive(:poll_for_exit).and_raise(ChildProcess::TimeoutError)
31
29
  allow(process).to receive(:send_kill).and_raise(Errno::ESRCH.new)
@@ -34,8 +32,6 @@ if ChildProcess.unix? && !ChildProcess.jruby? && !ChildProcess.posix_spawn?
34
32
  expect { process.stop }.not_to raise_error
35
33
 
36
34
  allow(process).to receive(:alive?).and_return(false)
37
-
38
- process.send(:send_signal, 'TERM')
39
35
  end
40
36
  end
41
37
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: childprocess
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jari Bakken
@@ -10,8 +10,22 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-06-09 00:00:00.000000000 Z
13
+ date: 2024-08-06 00:00:00.000000000 Z
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: logger
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '1.5'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '1.5'
15
29
  - !ruby/object:Gem::Dependency
16
30
  name: rspec
17
31
  requirement: !ruby/object:Gem::Requirement
@@ -64,49 +78,31 @@ extensions: []
64
78
  extra_rdoc_files: []
65
79
  files:
66
80
  - ".document"
81
+ - ".github/workflows/ci.yml"
67
82
  - ".gitignore"
68
83
  - ".rspec"
69
- - ".travis.yml"
70
84
  - CHANGELOG.md
71
85
  - Gemfile
72
86
  - LICENSE
73
87
  - README.md
74
88
  - Rakefile
75
- - appveyor.yml
76
89
  - childprocess.gemspec
77
90
  - lib/childprocess.rb
78
91
  - lib/childprocess/abstract_io.rb
79
92
  - lib/childprocess/abstract_process.rb
80
93
  - lib/childprocess/errors.rb
81
- - lib/childprocess/jruby.rb
82
- - lib/childprocess/jruby/io.rb
83
- - lib/childprocess/jruby/process.rb
84
- - lib/childprocess/jruby/pump.rb
85
- - lib/childprocess/tools/generator.rb
94
+ - lib/childprocess/process_spawn_process.rb
86
95
  - lib/childprocess/unix.rb
87
- - lib/childprocess/unix/fork_exec_process.rb
88
96
  - lib/childprocess/unix/io.rb
89
- - lib/childprocess/unix/lib.rb
90
- - lib/childprocess/unix/platform/arm64-macosx.rb
91
- - lib/childprocess/unix/platform/i386-linux.rb
92
- - lib/childprocess/unix/platform/i386-solaris.rb
93
- - lib/childprocess/unix/platform/x86_64-linux.rb
94
- - lib/childprocess/unix/platform/x86_64-macosx.rb
95
- - lib/childprocess/unix/posix_spawn_process.rb
96
97
  - lib/childprocess/unix/process.rb
97
98
  - lib/childprocess/version.rb
98
99
  - lib/childprocess/windows.rb
99
- - lib/childprocess/windows/handle.rb
100
100
  - lib/childprocess/windows/io.rb
101
- - lib/childprocess/windows/lib.rb
102
101
  - lib/childprocess/windows/process.rb
103
- - lib/childprocess/windows/process_builder.rb
104
- - lib/childprocess/windows/structs.rb
105
102
  - spec/abstract_io_spec.rb
106
103
  - spec/childprocess_spec.rb
107
104
  - spec/get_env.ps1
108
105
  - spec/io_spec.rb
109
- - spec/jruby_spec.rb
110
106
  - spec/pid_behavior.rb
111
107
  - spec/platform_detection_spec.rb
112
108
  - spec/spec_helper.rb
@@ -131,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
127
  - !ruby/object:Gem::Version
132
128
  version: '0'
133
129
  requirements: []
134
- rubygems_version: 3.1.4
130
+ rubygems_version: 3.5.9
135
131
  signing_key:
136
132
  specification_version: 4
137
133
  summary: A simple and reliable solution for controlling external programs running
@@ -141,7 +137,6 @@ test_files:
141
137
  - spec/childprocess_spec.rb
142
138
  - spec/get_env.ps1
143
139
  - spec/io_spec.rb
144
- - spec/jruby_spec.rb
145
140
  - spec/pid_behavior.rb
146
141
  - spec/platform_detection_spec.rb
147
142
  - spec/spec_helper.rb
data/.travis.yml DELETED
@@ -1,37 +0,0 @@
1
- os:
2
- - linux
3
- - osx
4
-
5
- rvm:
6
- - rbx-3
7
- - 2.4
8
- - 2.5
9
- - 2.6
10
- - ruby-head
11
-
12
- sudo: false
13
-
14
- cache: bundler
15
-
16
- before_install:
17
- - "echo 'gem: --no-document' > ~/.gemrc"
18
- - gem install bundler
19
-
20
- before_script:
21
- - 'export JAVA_OPTS="${JAVA_OPTS_FOR_SPECS}"'
22
-
23
- env:
24
- global:
25
- matrix:
26
- - CHILDPROCESS_POSIX_SPAWN=true CHILDPROCESS_UNSET=should-be-unset
27
- - CHILDPROCESS_POSIX_SPAWN=false CHILDPROCESS_UNSET=should-be-unset
28
-
29
- matrix:
30
- allow_failures:
31
- - rvm: rbx-3
32
- - rvm: ruby-head
33
- - env: "CHILDPROCESS_POSIX_SPAWN=true"
34
- include:
35
- - rvm: jruby-9.2.5.0
36
- jdk: openjdk11
37
- env: "JAVA_OPTS_FOR_SPECS='--add-opens java.base/java.io=org.jruby.dist --add-opens java.base/sun.nio.ch=org.jruby.dist'"
data/appveyor.yml DELETED
@@ -1,36 +0,0 @@
1
- version: '1.0.{build}'
2
-
3
- environment:
4
- matrix:
5
- - CHILDPROCESS_POSIX_SPAWN: true
6
- CHILDPROCESS_UNSET: should-be-unset
7
- RUBY_VERSION: 24-x64
8
- - CHILDPROCESS_POSIX_SPAWN: false
9
- CHILDPROCESS_UNSET: should-be-unset
10
- RUBY_VERSION: 24-x64
11
- - CHILDPROCESS_POSIX_SPAWN: true
12
- CHILDPROCESS_UNSET: should-be-unset
13
- RUBY_VERSION: 25-x64
14
- - CHILDPROCESS_POSIX_SPAWN: false
15
- CHILDPROCESS_UNSET: should-be-unset
16
- RUBY_VERSION: 25-x64
17
- - CHILDPROCESS_POSIX_SPAWN: true
18
- CHILDPROCESS_UNSET: should-be-unset
19
- RUBY_VERSION: 26-x64
20
- - CHILDPROCESS_POSIX_SPAWN: false
21
- CHILDPROCESS_UNSET: should-be-unset
22
- RUBY_VERSION: 26-x64
23
-
24
- install:
25
- - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH%
26
- - bundle install
27
-
28
- build: off
29
-
30
- before_test:
31
- - ruby -v
32
- - gem -v
33
- - bundle -v
34
-
35
- test_script:
36
- - bundle exec rake
@@ -1,16 +0,0 @@
1
- module ChildProcess
2
- module JRuby
3
- class IO < AbstractIO
4
- private
5
-
6
- def check_type(output)
7
- unless output.respond_to?(:to_outputstream) && output.respond_to?(:write)
8
- raise ArgumentError, "expected #{output.inspect} to respond to :to_outputstream"
9
- end
10
- end
11
-
12
- end # IO
13
- end # Unix
14
- end # ChildProcess
15
-
16
-