childprocess 0.3.9 → 0.4.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 +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +2 -2
- data/LICENSE +1 -1
- data/README.md +4 -1
- data/Rakefile +1 -1
- data/childprocess.gemspec +2 -0
- data/lib/childprocess/jruby/process.rb +7 -3
- data/lib/childprocess/unix/process.rb +6 -2
- data/lib/childprocess/version.rb +1 -1
- data/lib/childprocess/windows/process.rb +8 -5
- data/lib/childprocess/windows/process_builder.rb +23 -29
- data/spec/abstract_io_spec.rb +2 -2
- data/spec/childprocess_spec.rb +11 -4
- data/spec/io_spec.rb +7 -8
- data/spec/spec_helper.rb +7 -2
- data/spec/unix_spec.rb +8 -8
- metadata +29 -24
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 04d64c66d047e986bc57da09cbb13b3a4e791e28
|
4
|
+
data.tar.gz: ce4828aee09a5499e7f5858c93401dd42c851af9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d57f5c928a964451e325c06b60cf8680c1e0c0f3141b38ddb7d381e0914f5f4286871a8d4a1766e62375907963d7a977ff0d4f6732c4408e7eb8f7855f93894a
|
7
|
+
data.tar.gz: ddfcf22a34b38b47e5c7d42fab0b4a0449d0332b78dd118f191387ec72f81b8bbad9c68c94e08748c243aa7d3205f2b48edb0bd2977b0b5cc85d54905a347b35
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
rvm:
|
2
|
-
- 1.8.7
|
3
2
|
- 1.9.3
|
4
3
|
- jruby
|
5
4
|
- rbx
|
6
5
|
- 2.0.0
|
6
|
+
- 2.1.0
|
7
7
|
- ruby-head
|
8
8
|
env:
|
9
9
|
- CHILDPROCESS_POSIX_SPAWN=true
|
@@ -13,4 +13,4 @@ matrix:
|
|
13
13
|
- rvm: jruby
|
14
14
|
env: CHILDPROCESS_POSIX_SPAWN=true
|
15
15
|
- rvm: rbx
|
16
|
-
|
16
|
+
- rvm: ruby-head
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -7,6 +7,9 @@ The code originated in the [selenium-webdriver](https://rubygems.org/gems/seleni
|
|
7
7
|
a standalone library.
|
8
8
|
|
9
9
|
[](http://travis-ci.org/jarib/childprocess)
|
10
|
+
[](http://badge.fury.io/rb/childprocess)
|
11
|
+
[](https://codeclimate.com/github/jarib/childprocess)
|
12
|
+
[](https://coveralls.io/r/jarib/childprocess?branch=master)
|
10
13
|
|
11
14
|
# Usage
|
12
15
|
|
@@ -147,4 +150,4 @@ How the process is launched and killed depends on the platform:
|
|
147
150
|
|
148
151
|
# Copyright
|
149
152
|
|
150
|
-
Copyright (c) 2010-
|
153
|
+
Copyright (c) 2010-2014 Jari Bakken. See LICENSE for details.
|
data/Rakefile
CHANGED
data/childprocess.gemspec
CHANGED
@@ -13,6 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.description = %q{This gem aims at being a simple and reliable solution for controlling external programs running in the background on any Ruby / OS combination.}
|
14
14
|
|
15
15
|
s.rubyforge_project = "childprocess"
|
16
|
+
s.license = 'MIT'
|
16
17
|
|
17
18
|
s.files = `git ls-files`.split("\n")
|
18
19
|
s.test_files = `git ls-files -- spec/*`.split("\n")
|
@@ -21,6 +22,7 @@ Gem::Specification.new do |s|
|
|
21
22
|
s.add_development_dependency "rspec", ">= 2.0.0"
|
22
23
|
s.add_development_dependency "yard", ">= 0"
|
23
24
|
s.add_development_dependency "rake", "~> 0.9.2"
|
25
|
+
s.add_development_dependency 'coveralls'
|
24
26
|
s.add_runtime_dependency "ffi", "~> 1.0", ">= 1.0.11"
|
25
27
|
end
|
26
28
|
|
@@ -35,10 +35,14 @@ module ChildProcess
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def wait
|
38
|
-
|
38
|
+
if exited?
|
39
|
+
exit_code
|
40
|
+
else
|
41
|
+
@process.waitFor
|
39
42
|
|
40
|
-
|
41
|
-
|
43
|
+
stop_pumps
|
44
|
+
@exit_code = @process.exitValue
|
45
|
+
end
|
42
46
|
end
|
43
47
|
|
44
48
|
#
|
@@ -43,9 +43,13 @@ module ChildProcess
|
|
43
43
|
|
44
44
|
def wait
|
45
45
|
assert_started
|
46
|
-
pid, status = ::Process.waitpid2 @pid
|
47
46
|
|
48
|
-
|
47
|
+
if exited?
|
48
|
+
exit_code
|
49
|
+
else
|
50
|
+
_, status = ::Process.waitpid2 @pid
|
51
|
+
@exit_code = status.exitstatus || status.termsig
|
52
|
+
end
|
49
53
|
end
|
50
54
|
|
51
55
|
private
|
data/lib/childprocess/version.rb
CHANGED
@@ -21,11 +21,15 @@ module ChildProcess
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def wait
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
if exited?
|
25
|
+
exit_code
|
26
|
+
else
|
27
|
+
@handle.wait
|
28
|
+
@exit_code = @handle.exit_code
|
29
|
+
@handle.close
|
27
30
|
|
28
|
-
|
31
|
+
@exit_code
|
32
|
+
end
|
29
33
|
end
|
30
34
|
|
31
35
|
def exited?
|
@@ -49,7 +53,6 @@ module ChildProcess
|
|
49
53
|
|
50
54
|
def launch_process
|
51
55
|
builder = ProcessBuilder.new(@args)
|
52
|
-
builder.inherit = false
|
53
56
|
builder.detach = detach?
|
54
57
|
builder.duplex = duplex?
|
55
58
|
builder.environment = @environment unless @environment.empty?
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module ChildProcess
|
2
2
|
module Windows
|
3
3
|
class ProcessBuilder
|
4
|
-
attr_accessor :
|
4
|
+
attr_accessor :detach, :duplex, :environment, :stdout, :stderr, :cwd
|
5
5
|
attr_reader :stdin
|
6
6
|
|
7
7
|
def initialize(args)
|
8
8
|
@args = args
|
9
9
|
|
10
|
-
@inherit = false
|
11
10
|
@detach = false
|
12
11
|
@duplex = false
|
13
12
|
@environment = nil
|
@@ -76,7 +75,7 @@ module ChildProcess
|
|
76
75
|
@cmd_ptr, # command line
|
77
76
|
nil, # process attributes
|
78
77
|
nil, # thread attributes
|
79
|
-
|
78
|
+
true, # inherit handles
|
80
79
|
@flags, # creation flags
|
81
80
|
@env_ptr, # environment
|
82
81
|
@cwd_ptr, # current directory
|
@@ -102,40 +101,35 @@ module ChildProcess
|
|
102
101
|
end
|
103
102
|
|
104
103
|
def setup_io
|
105
|
-
|
106
|
-
|
107
|
-
startup_info[:dwFlags] |= STARTF_USESTDHANDLES
|
104
|
+
startup_info[:dwFlags] ||= 0
|
105
|
+
startup_info[:dwFlags] |= STARTF_USESTDHANDLES
|
108
106
|
|
109
|
-
|
110
|
-
|
111
|
-
if @stdout
|
112
|
-
startup_info[:hStdOutput] = std_stream_handle_for(@stdout)
|
113
|
-
end
|
114
|
-
|
115
|
-
if @stderr
|
116
|
-
startup_info[:hStdError] = std_stream_handle_for(@stderr)
|
117
|
-
end
|
107
|
+
if @stdout
|
108
|
+
startup_info[:hStdOutput] = std_stream_handle_for(@stdout)
|
118
109
|
end
|
119
110
|
|
120
|
-
|
121
|
-
|
111
|
+
if @stderr
|
112
|
+
startup_info[:hStdError] = std_stream_handle_for(@stderr)
|
113
|
+
end
|
122
114
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
115
|
+
if @duplex
|
116
|
+
read_pipe_ptr = FFI::MemoryPointer.new(:pointer)
|
117
|
+
write_pipe_ptr = FFI::MemoryPointer.new(:pointer)
|
118
|
+
sa = SecurityAttributes.new(:inherit => true)
|
127
119
|
|
128
|
-
|
129
|
-
|
120
|
+
ok = Lib.create_pipe(read_pipe_ptr, write_pipe_ptr, sa, 0)
|
121
|
+
Lib.check_error ok
|
130
122
|
|
131
|
-
|
132
|
-
|
123
|
+
@read_pipe = read_pipe_ptr.read_pointer
|
124
|
+
@write_pipe = write_pipe_ptr.read_pointer
|
133
125
|
|
134
|
-
|
135
|
-
|
136
|
-
Lib.set_handle_inheritance @write_pipe, false
|
126
|
+
Lib.set_handle_inheritance @read_pipe, true
|
127
|
+
Lib.set_handle_inheritance @write_pipe, false
|
137
128
|
|
138
|
-
|
129
|
+
startup_info[:hStdInput] = @read_pipe
|
130
|
+
else
|
131
|
+
startup_info[:hStdInput] = std_stream_handle_for(STDIN)
|
132
|
+
end
|
139
133
|
end
|
140
134
|
|
141
135
|
def std_stream_handle_for(io)
|
data/spec/abstract_io_spec.rb
CHANGED
data/spec/childprocess_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe ChildProcess do
|
|
6
6
|
it "returns self when started" do
|
7
7
|
process = sleeping_ruby
|
8
8
|
|
9
|
-
process.start.should
|
9
|
+
process.start.should eq process
|
10
10
|
process.should be_started
|
11
11
|
end
|
12
12
|
|
@@ -48,6 +48,13 @@ describe ChildProcess do
|
|
48
48
|
return_value.should == 0
|
49
49
|
end
|
50
50
|
|
51
|
+
it 'ignores #wait if process already finished' do
|
52
|
+
process = exit_with(0).start
|
53
|
+
sleep 0.01 until process.exited?
|
54
|
+
|
55
|
+
process.wait.should == 0
|
56
|
+
end
|
57
|
+
|
51
58
|
it "escalates if TERM is ignored" do
|
52
59
|
process = ignored('TERM').start
|
53
60
|
process.stop
|
@@ -100,8 +107,8 @@ describe ChildProcess do
|
|
100
107
|
file.rewind
|
101
108
|
child_env = eval(file.read)
|
102
109
|
|
103
|
-
child_env['INHERITED'].should
|
104
|
-
child_env['CHILD_ONLY'].should
|
110
|
+
child_env['INHERITED'].should eq 'yes'
|
111
|
+
child_env['CHILD_ONLY'].should eq 'yes'
|
105
112
|
end
|
106
113
|
end
|
107
114
|
end
|
@@ -172,7 +179,7 @@ describe ChildProcess do
|
|
172
179
|
path = File.expand_path('foo bar')
|
173
180
|
|
174
181
|
with_executable_at(path) do |proc|
|
175
|
-
proc.start.should
|
182
|
+
proc.start.should eq proc
|
176
183
|
proc.should be_started
|
177
184
|
end
|
178
185
|
end
|
data/spec/io_spec.rb
CHANGED
@@ -23,8 +23,8 @@ describe ChildProcess do
|
|
23
23
|
out.rewind
|
24
24
|
err.rewind
|
25
25
|
|
26
|
-
out.read.should
|
27
|
-
err.read.should
|
26
|
+
out.read.should eq "0\n"
|
27
|
+
err.read.should eq "1\n"
|
28
28
|
ensure
|
29
29
|
out.close
|
30
30
|
err.close
|
@@ -113,27 +113,26 @@ describe ChildProcess do
|
|
113
113
|
process.start
|
114
114
|
|
115
115
|
stdin = process.io.stdin
|
116
|
-
lf = ChildProcess.windows? ? "\r\n" : "\n"
|
117
116
|
|
118
117
|
stdin.puts "hello"
|
119
118
|
stdin.flush
|
120
|
-
wait_until { rewind_and_read(out_receiver).should
|
119
|
+
wait_until { rewind_and_read(out_receiver).should =~ /\Ahello\r?\n\z/m }
|
121
120
|
|
122
121
|
stdin.putc "n"
|
123
122
|
stdin.flush
|
124
|
-
wait_until { rewind_and_read(out_receiver).should
|
123
|
+
wait_until { rewind_and_read(out_receiver).should =~ /\Ahello\r?\nn\z/m }
|
125
124
|
|
126
125
|
stdin.print "e"
|
127
126
|
stdin.flush
|
128
|
-
wait_until { rewind_and_read(out_receiver).should
|
127
|
+
wait_until { rewind_and_read(out_receiver).should =~ /\Ahello\r?\nne\z/m }
|
129
128
|
|
130
129
|
stdin.printf "w"
|
131
130
|
stdin.flush
|
132
|
-
wait_until { rewind_and_read(out_receiver).should
|
131
|
+
wait_until { rewind_and_read(out_receiver).should =~ /\Ahello\r?\nnew\z/m }
|
133
132
|
|
134
133
|
stdin.write "\nworld\n"
|
135
134
|
stdin.flush
|
136
|
-
wait_until { rewind_and_read(out_receiver).should
|
135
|
+
wait_until { rewind_and_read(out_receiver).should =~ /\Ahello\r?\nnew\r?\nworld\r?\n\z/m }
|
137
136
|
|
138
137
|
stdin.close
|
139
138
|
process.poll_for_exit(exit_timeout)
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
2
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
3
|
|
4
|
+
unless defined?(JRUBY_VERSION)
|
5
|
+
require 'coveralls'
|
6
|
+
Coveralls.wear!
|
7
|
+
end
|
8
|
+
|
4
9
|
require 'childprocess'
|
5
10
|
require 'rspec'
|
6
11
|
require 'tempfile'
|
@@ -175,7 +180,7 @@ module ChildProcessSpecHelper
|
|
175
180
|
last_exception = ex
|
176
181
|
end
|
177
182
|
|
178
|
-
sleep 0.
|
183
|
+
sleep 0.01
|
179
184
|
end
|
180
185
|
|
181
186
|
msg = "timed out after #{timeout} seconds"
|
@@ -203,7 +208,7 @@ Thread.abort_on_exception = true
|
|
203
208
|
RSpec.configure do |c|
|
204
209
|
c.include(ChildProcessSpecHelper)
|
205
210
|
c.after(:each) {
|
206
|
-
@process && @process.alive? && @process.stop
|
211
|
+
defined?(@process) && @process.alive? && @process.stop
|
207
212
|
}
|
208
213
|
|
209
214
|
if ChildProcess.jruby? && ChildProcess.new("true").instance_of?(ChildProcess::JRuby::Process)
|
data/spec/unix_spec.rb
CHANGED
@@ -9,10 +9,10 @@ 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
|
-
process.stub
|
13
|
-
process.stub
|
14
|
-
process.stub
|
15
|
-
process.stub
|
12
|
+
process.stub(:fork).and_return('fakepid')
|
13
|
+
process.stub(:send_term)
|
14
|
+
process.stub(:poll_for_exit).and_raise(ChildProcess::TimeoutError)
|
15
|
+
process.stub(:send_kill).and_raise(Errno::ECHILD.new)
|
16
16
|
|
17
17
|
process.start
|
18
18
|
lambda { process.stop }.should_not raise_error
|
@@ -23,10 +23,10 @@ if ChildProcess.unix? && !ChildProcess.jruby? && !ChildProcess.posix_spawn?
|
|
23
23
|
it "handles ESRCH race condition where process dies between timeout and KILL" do
|
24
24
|
process = sleeping_ruby
|
25
25
|
|
26
|
-
process.stub
|
27
|
-
process.stub
|
28
|
-
process.stub
|
29
|
-
process.stub
|
26
|
+
process.stub(:fork).and_return('fakepid')
|
27
|
+
process.stub(:send_term)
|
28
|
+
process.stub(:poll_for_exit).and_raise(ChildProcess::TimeoutError)
|
29
|
+
process.stub(:send_kill).and_raise(Errno::ESRCH.new)
|
30
30
|
|
31
31
|
process.start
|
32
32
|
lambda { process.stop }.should_not raise_error
|
metadata
CHANGED
@@ -1,52 +1,46 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: childprocess
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jari Bakken
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-18 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rspec
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 2.0.0
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 2.0.0
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: yard
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rake
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ~>
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,31 +48,42 @@ dependencies:
|
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: 0.9.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: coveralls
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
62
69
|
- !ruby/object:Gem::Dependency
|
63
70
|
name: ffi
|
64
71
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
72
|
requirements:
|
67
73
|
- - ~>
|
68
74
|
- !ruby/object:Gem::Version
|
69
75
|
version: '1.0'
|
70
|
-
- -
|
76
|
+
- - '>='
|
71
77
|
- !ruby/object:Gem::Version
|
72
78
|
version: 1.0.11
|
73
79
|
type: :runtime
|
74
80
|
prerelease: false
|
75
81
|
version_requirements: !ruby/object:Gem::Requirement
|
76
|
-
none: false
|
77
82
|
requirements:
|
78
83
|
- - ~>
|
79
84
|
- !ruby/object:Gem::Version
|
80
85
|
version: '1.0'
|
81
|
-
- -
|
86
|
+
- - '>='
|
82
87
|
- !ruby/object:Gem::Version
|
83
88
|
version: 1.0.11
|
84
89
|
description: This gem aims at being a simple and reliable solution for controlling
|
@@ -134,28 +139,28 @@ files:
|
|
134
139
|
- spec/unix_spec.rb
|
135
140
|
- spec/windows_spec.rb
|
136
141
|
homepage: http://github.com/jarib/childprocess
|
137
|
-
licenses:
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
metadata: {}
|
138
145
|
post_install_message:
|
139
146
|
rdoc_options: []
|
140
147
|
require_paths:
|
141
148
|
- lib
|
142
149
|
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
-
none: false
|
144
150
|
requirements:
|
145
|
-
- -
|
151
|
+
- - '>='
|
146
152
|
- !ruby/object:Gem::Version
|
147
153
|
version: '0'
|
148
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
-
none: false
|
150
155
|
requirements:
|
151
|
-
- -
|
156
|
+
- - '>='
|
152
157
|
- !ruby/object:Gem::Version
|
153
158
|
version: '0'
|
154
159
|
requirements: []
|
155
160
|
rubyforge_project: childprocess
|
156
|
-
rubygems_version:
|
161
|
+
rubygems_version: 2.0.14
|
157
162
|
signing_key:
|
158
|
-
specification_version:
|
163
|
+
specification_version: 4
|
159
164
|
summary: This gem aims at being a simple and reliable solution for controlling external
|
160
165
|
programs running in the background on any Ruby / OS combination.
|
161
166
|
test_files:
|