childprocess 4.1.0 → 5.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +23 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +0 -2
- data/README.md +3 -20
- data/lib/childprocess/abstract_process.rb +1 -1
- data/lib/childprocess/errors.rb +0 -21
- data/lib/childprocess/process_spawn_process.rb +127 -0
- data/lib/childprocess/unix/process.rb +3 -64
- data/lib/childprocess/unix.rb +2 -4
- data/lib/childprocess/version.rb +1 -1
- data/lib/childprocess/windows/process.rb +13 -116
- data/lib/childprocess/windows.rb +0 -29
- data/lib/childprocess.rb +16 -53
- data/spec/childprocess_spec.rb +39 -15
- data/spec/io_spec.rb +1 -1
- data/spec/spec_helper.rb +3 -18
- data/spec/unix_spec.rb +3 -7
- metadata +8 -27
- data/.travis.yml +0 -37
- data/appveyor.yml +0 -36
- data/lib/childprocess/jruby/io.rb +0 -16
- data/lib/childprocess/jruby/process.rb +0 -184
- data/lib/childprocess/jruby/pump.rb +0 -53
- data/lib/childprocess/jruby.rb +0 -56
- data/lib/childprocess/tools/generator.rb +0 -146
- data/lib/childprocess/unix/fork_exec_process.rb +0 -78
- data/lib/childprocess/unix/lib.rb +0 -186
- data/lib/childprocess/unix/platform/arm64-macosx.rb +0 -11
- data/lib/childprocess/unix/platform/i386-linux.rb +0 -12
- data/lib/childprocess/unix/platform/i386-solaris.rb +0 -11
- data/lib/childprocess/unix/platform/x86_64-linux.rb +0 -12
- data/lib/childprocess/unix/platform/x86_64-macosx.rb +0 -11
- data/lib/childprocess/unix/posix_spawn_process.rb +0 -134
- data/lib/childprocess/windows/handle.rb +0 -91
- data/lib/childprocess/windows/lib.rb +0 -416
- data/lib/childprocess/windows/process_builder.rb +0 -178
- data/lib/childprocess/windows/structs.rb +0 -149
- data/spec/jruby_spec.rb +0 -24
data/spec/childprocess_spec.rb
CHANGED
@@ -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
|
-
|
15
|
-
|
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
|
-
|
18
|
-
|
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
|
-
|
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
|
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'
|
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"
|
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
@@ -210,16 +210,9 @@ module ChildProcessSpecHelper
|
|
210
210
|
end
|
211
211
|
|
212
212
|
def alive?(pid)
|
213
|
-
|
214
|
-
|
215
|
-
|
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
|
@@ -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?
|
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(
|
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(
|
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,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: childprocess
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jari Bakken
|
8
8
|
- Eric Kessler
|
9
9
|
- Shane da Silva
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2024-01-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -64,49 +64,31 @@ extensions: []
|
|
64
64
|
extra_rdoc_files: []
|
65
65
|
files:
|
66
66
|
- ".document"
|
67
|
+
- ".github/workflows/ci.yml"
|
67
68
|
- ".gitignore"
|
68
69
|
- ".rspec"
|
69
|
-
- ".travis.yml"
|
70
70
|
- CHANGELOG.md
|
71
71
|
- Gemfile
|
72
72
|
- LICENSE
|
73
73
|
- README.md
|
74
74
|
- Rakefile
|
75
|
-
- appveyor.yml
|
76
75
|
- childprocess.gemspec
|
77
76
|
- lib/childprocess.rb
|
78
77
|
- lib/childprocess/abstract_io.rb
|
79
78
|
- lib/childprocess/abstract_process.rb
|
80
79
|
- lib/childprocess/errors.rb
|
81
|
-
- lib/childprocess/
|
82
|
-
- lib/childprocess/jruby/io.rb
|
83
|
-
- lib/childprocess/jruby/process.rb
|
84
|
-
- lib/childprocess/jruby/pump.rb
|
85
|
-
- lib/childprocess/tools/generator.rb
|
80
|
+
- lib/childprocess/process_spawn_process.rb
|
86
81
|
- lib/childprocess/unix.rb
|
87
|
-
- lib/childprocess/unix/fork_exec_process.rb
|
88
82
|
- 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
83
|
- lib/childprocess/unix/process.rb
|
97
84
|
- lib/childprocess/version.rb
|
98
85
|
- lib/childprocess/windows.rb
|
99
|
-
- lib/childprocess/windows/handle.rb
|
100
86
|
- lib/childprocess/windows/io.rb
|
101
|
-
- lib/childprocess/windows/lib.rb
|
102
87
|
- lib/childprocess/windows/process.rb
|
103
|
-
- lib/childprocess/windows/process_builder.rb
|
104
|
-
- lib/childprocess/windows/structs.rb
|
105
88
|
- spec/abstract_io_spec.rb
|
106
89
|
- spec/childprocess_spec.rb
|
107
90
|
- spec/get_env.ps1
|
108
91
|
- spec/io_spec.rb
|
109
|
-
- spec/jruby_spec.rb
|
110
92
|
- spec/pid_behavior.rb
|
111
93
|
- spec/platform_detection_spec.rb
|
112
94
|
- spec/spec_helper.rb
|
@@ -116,7 +98,7 @@ homepage: https://github.com/enkessler/childprocess
|
|
116
98
|
licenses:
|
117
99
|
- MIT
|
118
100
|
metadata: {}
|
119
|
-
post_install_message:
|
101
|
+
post_install_message:
|
120
102
|
rdoc_options: []
|
121
103
|
require_paths:
|
122
104
|
- lib
|
@@ -131,8 +113,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
113
|
- !ruby/object:Gem::Version
|
132
114
|
version: '0'
|
133
115
|
requirements: []
|
134
|
-
rubygems_version: 3.1
|
135
|
-
signing_key:
|
116
|
+
rubygems_version: 3.0.3.1
|
117
|
+
signing_key:
|
136
118
|
specification_version: 4
|
137
119
|
summary: A simple and reliable solution for controlling external programs running
|
138
120
|
in the background on any Ruby / OS combination.
|
@@ -141,7 +123,6 @@ test_files:
|
|
141
123
|
- spec/childprocess_spec.rb
|
142
124
|
- spec/get_env.ps1
|
143
125
|
- spec/io_spec.rb
|
144
|
-
- spec/jruby_spec.rb
|
145
126
|
- spec/pid_behavior.rb
|
146
127
|
- spec/platform_detection_spec.rb
|
147
128
|
- 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
|
-
|
@@ -1,184 +0,0 @@
|
|
1
|
-
require "java"
|
2
|
-
|
3
|
-
module ChildProcess
|
4
|
-
module JRuby
|
5
|
-
class Process < AbstractProcess
|
6
|
-
def initialize(args)
|
7
|
-
super(args)
|
8
|
-
|
9
|
-
@pumps = []
|
10
|
-
end
|
11
|
-
|
12
|
-
def io
|
13
|
-
@io ||= JRuby::IO.new
|
14
|
-
end
|
15
|
-
|
16
|
-
def exited?
|
17
|
-
return true if @exit_code
|
18
|
-
|
19
|
-
assert_started
|
20
|
-
@exit_code = @process.exitValue
|
21
|
-
stop_pumps
|
22
|
-
|
23
|
-
true
|
24
|
-
rescue java.lang.IllegalThreadStateException => ex
|
25
|
-
log(ex.class => ex.message)
|
26
|
-
false
|
27
|
-
ensure
|
28
|
-
log(:exit_code => @exit_code)
|
29
|
-
end
|
30
|
-
|
31
|
-
def stop(timeout = nil)
|
32
|
-
assert_started
|
33
|
-
|
34
|
-
@process.destroy
|
35
|
-
wait # no way to actually use the timeout here..
|
36
|
-
end
|
37
|
-
|
38
|
-
def wait
|
39
|
-
if exited?
|
40
|
-
exit_code
|
41
|
-
else
|
42
|
-
@process.waitFor
|
43
|
-
|
44
|
-
stop_pumps
|
45
|
-
@exit_code = @process.exitValue
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# Implementation of ChildProcess::JRuby::Process#pid depends heavily on
|
50
|
-
# what Java SDK is being used; here, we look it up once at load, then
|
51
|
-
# define the method once to avoid runtime overhead.
|
52
|
-
normalised_java_version_major = java.lang.System.get_property("java.version")
|
53
|
-
.slice(/^(1\.)?([0-9]+)/, 2)
|
54
|
-
.to_i
|
55
|
-
if normalised_java_version_major >= 9
|
56
|
-
|
57
|
-
# On modern Javas, we can simply delegate through to `Process#pid`,
|
58
|
-
# which was introduced in Java 9.
|
59
|
-
#
|
60
|
-
# @return [Integer] the pid of the process after it has started
|
61
|
-
# @raise [NotImplementedError] when trying to access pid on platform for
|
62
|
-
# which it is unsupported in Java
|
63
|
-
def pid
|
64
|
-
@process.pid
|
65
|
-
rescue java.lang.UnsupportedOperationException => e
|
66
|
-
raise NotImplementedError, "pid is not supported on this platform: #{e.message}"
|
67
|
-
end
|
68
|
-
|
69
|
-
else
|
70
|
-
|
71
|
-
# On Legacy Javas, fall back to reflection.
|
72
|
-
#
|
73
|
-
# Only supported in JRuby on a Unix operating system, thanks to limitations
|
74
|
-
# in Java's classes
|
75
|
-
#
|
76
|
-
# @return [Integer] the pid of the process after it has started
|
77
|
-
# @raise [NotImplementedError] when trying to access pid on non-Unix platform
|
78
|
-
#
|
79
|
-
def pid
|
80
|
-
if @process.getClass.getName != "java.lang.UNIXProcess"
|
81
|
-
raise NotImplementedError, "pid is only supported by JRuby child processes on Unix"
|
82
|
-
end
|
83
|
-
|
84
|
-
# About the best way we can do this is with a nasty reflection-based impl
|
85
|
-
# Thanks to Martijn Courteaux
|
86
|
-
# http://stackoverflow.com/questions/2950338/how-can-i-kill-a-linux-process-in-java-with-sigkill-process-destroy-does-sigter/2951193#2951193
|
87
|
-
field = @process.getClass.getDeclaredField("pid")
|
88
|
-
field.accessible = true
|
89
|
-
field.get(@process)
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def launch_process(&blk)
|
97
|
-
pb = java.lang.ProcessBuilder.new(@args)
|
98
|
-
|
99
|
-
pb.directory java.io.File.new(@cwd || Dir.pwd)
|
100
|
-
set_env pb.environment
|
101
|
-
|
102
|
-
begin
|
103
|
-
@process = pb.start
|
104
|
-
rescue java.io.IOException => ex
|
105
|
-
raise LaunchError, ex.message
|
106
|
-
end
|
107
|
-
|
108
|
-
setup_io
|
109
|
-
end
|
110
|
-
|
111
|
-
def setup_io
|
112
|
-
if @io
|
113
|
-
redirect(@process.getErrorStream, @io.stderr)
|
114
|
-
redirect(@process.getInputStream, @io.stdout)
|
115
|
-
else
|
116
|
-
@process.getErrorStream.close
|
117
|
-
@process.getInputStream.close
|
118
|
-
end
|
119
|
-
|
120
|
-
if duplex?
|
121
|
-
io._stdin = create_stdin
|
122
|
-
else
|
123
|
-
@process.getOutputStream.close
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def redirect(input, output)
|
128
|
-
if output.nil?
|
129
|
-
input.close
|
130
|
-
return
|
131
|
-
end
|
132
|
-
|
133
|
-
@pumps << Pump.new(input, output.to_outputstream).run
|
134
|
-
end
|
135
|
-
|
136
|
-
def stop_pumps
|
137
|
-
@pumps.each { |pump| pump.stop }
|
138
|
-
end
|
139
|
-
|
140
|
-
def set_env(env)
|
141
|
-
merged = ENV.to_hash
|
142
|
-
|
143
|
-
@environment.each { |k, v| merged[k.to_s] = v }
|
144
|
-
|
145
|
-
merged.each do |k, v|
|
146
|
-
if v
|
147
|
-
env.put(k, v.to_s)
|
148
|
-
elsif env.has_key? k
|
149
|
-
env.remove(k)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
removed_keys = env.key_set.to_a - merged.keys
|
154
|
-
removed_keys.each { |k| env.remove(k) }
|
155
|
-
end
|
156
|
-
|
157
|
-
def create_stdin
|
158
|
-
output_stream = @process.getOutputStream
|
159
|
-
|
160
|
-
stdin = output_stream.to_io
|
161
|
-
stdin.sync = true
|
162
|
-
stdin.instance_variable_set(:@childprocess_java_stream, output_stream)
|
163
|
-
|
164
|
-
class << stdin
|
165
|
-
# The stream provided is a BufferedeOutputStream, so we
|
166
|
-
# have to flush it to make the bytes flow to the process
|
167
|
-
def __childprocess_flush__
|
168
|
-
@childprocess_java_stream.flush
|
169
|
-
end
|
170
|
-
|
171
|
-
[:flush, :print, :printf, :putc, :puts, :write, :write_nonblock].each do |m|
|
172
|
-
define_method(m) do |*args|
|
173
|
-
super(*args)
|
174
|
-
self.__childprocess_flush__
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
stdin
|
180
|
-
end
|
181
|
-
|
182
|
-
end # Process
|
183
|
-
end # JRuby
|
184
|
-
end # ChildProcess
|
@@ -1,53 +0,0 @@
|
|
1
|
-
module ChildProcess
|
2
|
-
module JRuby
|
3
|
-
class Pump
|
4
|
-
BUFFER_SIZE = 2048
|
5
|
-
|
6
|
-
def initialize(input, output)
|
7
|
-
@input = input
|
8
|
-
@output = output
|
9
|
-
@stop = false
|
10
|
-
end
|
11
|
-
|
12
|
-
def stop
|
13
|
-
@stop = true
|
14
|
-
@thread && @thread.join
|
15
|
-
end
|
16
|
-
|
17
|
-
def run
|
18
|
-
@thread = Thread.new { pump }
|
19
|
-
|
20
|
-
self
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def pump
|
26
|
-
buffer = Java.byte[BUFFER_SIZE].new
|
27
|
-
|
28
|
-
until @stop && (@input.available == 0)
|
29
|
-
read, avail = 0, 0
|
30
|
-
|
31
|
-
while read != -1
|
32
|
-
avail = [@input.available, 1].max
|
33
|
-
avail = BUFFER_SIZE if avail > BUFFER_SIZE
|
34
|
-
read = @input.read(buffer, 0, avail)
|
35
|
-
|
36
|
-
if read > 0
|
37
|
-
@output.write(buffer, 0, read)
|
38
|
-
@output.flush
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
sleep 0.1
|
43
|
-
end
|
44
|
-
|
45
|
-
@output.flush
|
46
|
-
rescue java.io.IOException => ex
|
47
|
-
ChildProcess.logger.debug ex.message
|
48
|
-
ChildProcess.logger.debug ex.backtrace
|
49
|
-
end
|
50
|
-
|
51
|
-
end # Pump
|
52
|
-
end # JRuby
|
53
|
-
end # ChildProcess
|
data/lib/childprocess/jruby.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'java'
|
2
|
-
require 'jruby'
|
3
|
-
|
4
|
-
class Java::SunNioCh::FileChannelImpl
|
5
|
-
field_reader :fd
|
6
|
-
end
|
7
|
-
|
8
|
-
class Java::JavaIo::FileDescriptor
|
9
|
-
if ChildProcess.os == :windows
|
10
|
-
field_reader :handle
|
11
|
-
end
|
12
|
-
|
13
|
-
field_reader :fd
|
14
|
-
end
|
15
|
-
|
16
|
-
module ChildProcess
|
17
|
-
module JRuby
|
18
|
-
def self.posix_fileno_for(obj)
|
19
|
-
channel = ::JRuby.reference(obj).channel
|
20
|
-
begin
|
21
|
-
channel.getFDVal
|
22
|
-
rescue NoMethodError
|
23
|
-
fileno = channel.fd
|
24
|
-
if fileno.kind_of?(Java::JavaIo::FileDescriptor)
|
25
|
-
fileno = fileno.fd
|
26
|
-
end
|
27
|
-
|
28
|
-
fileno == -1 ? obj.fileno : fileno
|
29
|
-
end
|
30
|
-
rescue
|
31
|
-
# fall back
|
32
|
-
obj.fileno
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.windows_handle_for(obj)
|
36
|
-
channel = ::JRuby.reference(obj).channel
|
37
|
-
fileno = obj.fileno
|
38
|
-
|
39
|
-
begin
|
40
|
-
fileno = channel.getFDVal
|
41
|
-
rescue NoMethodError
|
42
|
-
fileno = channel.fd if channel.respond_to?(:fd)
|
43
|
-
end
|
44
|
-
|
45
|
-
if fileno.kind_of? Java::JavaIo::FileDescriptor
|
46
|
-
fileno.handle
|
47
|
-
else
|
48
|
-
Windows::Lib.handle_for fileno
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
require "childprocess/jruby/pump"
|
55
|
-
require "childprocess/jruby/io"
|
56
|
-
require "childprocess/jruby/process"
|