childprocess 0.3.9 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://secure.travis-ci.org/jarib/childprocess.png)](http://travis-ci.org/jarib/childprocess)
|
10
|
+
[![Gem Version](https://badge.fury.io/rb/childprocess.png)](http://badge.fury.io/rb/childprocess)
|
11
|
+
[![Code Climate](https://codeclimate.com/github/jarib/childprocess.png)](https://codeclimate.com/github/jarib/childprocess)
|
12
|
+
[![Coverage Status](https://coveralls.io/repos/jarib/childprocess/badge.png?branch=master)](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:
|