childprocess 0.8.0 → 2.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 +5 -5
- data/.document +6 -6
- data/.gitignore +28 -28
- data/.rspec +1 -1
- data/.travis.yml +42 -36
- data/CHANGELOG.md +67 -44
- data/Gemfile +18 -15
- data/LICENSE +20 -20
- data/README.md +216 -192
- data/Rakefile +61 -61
- data/appveyor.yml +42 -43
- data/childprocess.gemspec +32 -30
- data/ext/mkrf_conf.rb +24 -0
- data/lib/childprocess/abstract_io.rb +36 -36
- data/lib/childprocess/abstract_process.rb +192 -192
- data/lib/childprocess/errors.rb +37 -26
- data/lib/childprocess/jruby/io.rb +16 -16
- data/lib/childprocess/jruby/process.rb +184 -159
- data/lib/childprocess/jruby/pump.rb +53 -53
- data/lib/childprocess/jruby.rb +56 -56
- data/lib/childprocess/tools/generator.rb +145 -145
- data/lib/childprocess/unix/fork_exec_process.rb +78 -70
- data/lib/childprocess/unix/io.rb +21 -21
- data/lib/childprocess/unix/lib.rb +186 -186
- data/lib/childprocess/unix/platform/i386-linux.rb +12 -12
- data/lib/childprocess/unix/platform/i386-solaris.rb +11 -11
- data/lib/childprocess/unix/platform/x86_64-linux.rb +12 -12
- data/lib/childprocess/unix/platform/x86_64-macosx.rb +11 -11
- data/lib/childprocess/unix/posix_spawn_process.rb +134 -134
- data/lib/childprocess/unix/process.rb +90 -89
- data/lib/childprocess/unix.rb +9 -9
- data/lib/childprocess/version.rb +3 -3
- data/lib/childprocess/windows/handle.rb +91 -91
- data/lib/childprocess/windows/io.rb +25 -25
- data/lib/childprocess/windows/lib.rb +416 -416
- data/lib/childprocess/windows/process.rb +130 -130
- data/lib/childprocess/windows/process_builder.rb +178 -175
- data/lib/childprocess/windows/structs.rb +148 -148
- data/lib/childprocess/windows.rb +33 -33
- data/lib/childprocess.rb +210 -205
- data/spec/abstract_io_spec.rb +12 -12
- data/spec/childprocess_spec.rb +447 -391
- data/spec/get_env.ps1 +13 -0
- data/spec/io_spec.rb +228 -228
- data/spec/jruby_spec.rb +24 -24
- data/spec/pid_behavior.rb +12 -12
- data/spec/platform_detection_spec.rb +86 -86
- data/spec/spec_helper.rb +270 -261
- data/spec/unix_spec.rb +57 -57
- data/spec/windows_spec.rb +23 -23
- metadata +18 -33
data/childprocess.gemspec
CHANGED
@@ -1,30 +1,32 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "childprocess/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "childprocess"
|
7
|
-
s.version = ChildProcess::VERSION
|
8
|
-
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = ["Jari Bakken", "Eric Kessler"]
|
10
|
-
s.email = ["morrow748@gmail.com"]
|
11
|
-
s.homepage = "http://github.com/enkessler/childprocess"
|
12
|
-
s.summary = %q{A simple and reliable solution for controlling external programs running in the background on any Ruby / OS combination.}
|
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
|
-
|
15
|
-
s.rubyforge_project = "childprocess"
|
16
|
-
s.license = 'MIT'
|
17
|
-
|
18
|
-
s.files = `git ls-files`.split("\n")
|
19
|
-
s.test_files = `git ls-files -- spec/*`.split("\n")
|
20
|
-
s.require_paths = ["lib"]
|
21
|
-
|
22
|
-
s.
|
23
|
-
|
24
|
-
s.add_development_dependency "rspec", "~> 3.0"
|
25
|
-
s.add_development_dependency "yard", "~> 0.0"
|
26
|
-
s.add_development_dependency '
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "childprocess/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "childprocess"
|
7
|
+
s.version = ChildProcess::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Jari Bakken", "Eric Kessler", "Shane da Silva"]
|
10
|
+
s.email = ["morrow748@gmail.com", "shane@dasilva.io"]
|
11
|
+
s.homepage = "http://github.com/enkessler/childprocess"
|
12
|
+
s.summary = %q{A simple and reliable solution for controlling external programs running in the background on any Ruby / OS combination.}
|
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
|
+
|
15
|
+
s.rubyforge_project = "childprocess"
|
16
|
+
s.license = 'MIT'
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.required_ruby_version = '>= 2.3.0'
|
23
|
+
|
24
|
+
s.add_development_dependency "rspec", "~> 3.0"
|
25
|
+
s.add_development_dependency "yard", "~> 0.0"
|
26
|
+
s.add_development_dependency 'coveralls', '< 1.0'
|
27
|
+
|
28
|
+
s.add_runtime_dependency 'rake', '< 13.0'
|
29
|
+
|
30
|
+
# Install FFI gem if we're running on Windows
|
31
|
+
s.extensions = 'ext/mkrf_conf.rb'
|
32
|
+
end
|
data/ext/mkrf_conf.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Based on the example from https://en.wikibooks.org/wiki/Ruby_Programming/RubyGems#How_to_install_different_versions_of_gems_depending_on_which_version_of_ruby_the_installee_is_using
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rubygems/command.rb'
|
4
|
+
require 'rubygems/dependency_installer.rb'
|
5
|
+
|
6
|
+
begin
|
7
|
+
Gem::Command.build_args = ARGV
|
8
|
+
rescue NoMethodError # rubocop:disable Lint/HandleExceptions
|
9
|
+
end
|
10
|
+
|
11
|
+
inst = Gem::DependencyInstaller.new
|
12
|
+
|
13
|
+
begin
|
14
|
+
if Gem.win_platform?
|
15
|
+
inst.install 'ffi', Gem::Requirement.new('~> 1.0', '>= 1.0.11')
|
16
|
+
end
|
17
|
+
rescue # rubocop:disable Lint/RescueWithoutErrorClass
|
18
|
+
exit(1)
|
19
|
+
end
|
20
|
+
|
21
|
+
# create dummy rakefile to indicate success
|
22
|
+
File.open(File.join(File.dirname(__FILE__), 'Rakefile'), 'w') do |f|
|
23
|
+
f.write("task :default\n")
|
24
|
+
end
|
@@ -1,36 +1,36 @@
|
|
1
|
-
module ChildProcess
|
2
|
-
class AbstractIO
|
3
|
-
attr_reader :stderr, :stdout, :stdin
|
4
|
-
|
5
|
-
def inherit!
|
6
|
-
@stdout = STDOUT
|
7
|
-
@stderr = STDERR
|
8
|
-
end
|
9
|
-
|
10
|
-
def stderr=(io)
|
11
|
-
check_type io
|
12
|
-
@stderr = io
|
13
|
-
end
|
14
|
-
|
15
|
-
def stdout=(io)
|
16
|
-
check_type io
|
17
|
-
@stdout = io
|
18
|
-
end
|
19
|
-
|
20
|
-
#
|
21
|
-
# @api private
|
22
|
-
#
|
23
|
-
|
24
|
-
def _stdin=(io)
|
25
|
-
check_type io
|
26
|
-
@stdin = io
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def check_type(io)
|
32
|
-
raise SubclassResponsibility, "check_type"
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
1
|
+
module ChildProcess
|
2
|
+
class AbstractIO
|
3
|
+
attr_reader :stderr, :stdout, :stdin
|
4
|
+
|
5
|
+
def inherit!
|
6
|
+
@stdout = STDOUT
|
7
|
+
@stderr = STDERR
|
8
|
+
end
|
9
|
+
|
10
|
+
def stderr=(io)
|
11
|
+
check_type io
|
12
|
+
@stderr = io
|
13
|
+
end
|
14
|
+
|
15
|
+
def stdout=(io)
|
16
|
+
check_type io
|
17
|
+
@stdout = io
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
#
|
23
|
+
|
24
|
+
def _stdin=(io)
|
25
|
+
check_type io
|
26
|
+
@stdin = io
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def check_type(io)
|
32
|
+
raise SubclassResponsibility, "check_type"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -1,192 +1,192 @@
|
|
1
|
-
module ChildProcess
|
2
|
-
class AbstractProcess
|
3
|
-
POLL_INTERVAL = 0.1
|
4
|
-
|
5
|
-
attr_reader :exit_code
|
6
|
-
|
7
|
-
#
|
8
|
-
# Set this to true if you do not care about when or if the process quits.
|
9
|
-
#
|
10
|
-
attr_accessor :detach
|
11
|
-
|
12
|
-
#
|
13
|
-
# Set this to true if you want to write to the process' stdin (process.io.stdin)
|
14
|
-
#
|
15
|
-
attr_accessor :duplex
|
16
|
-
|
17
|
-
#
|
18
|
-
# Modify the child's environment variables
|
19
|
-
#
|
20
|
-
attr_reader :environment
|
21
|
-
|
22
|
-
#
|
23
|
-
# Set the child's current working directory.
|
24
|
-
#
|
25
|
-
attr_accessor :cwd
|
26
|
-
|
27
|
-
#
|
28
|
-
# Set this to true to make the child process the leader of a new process group
|
29
|
-
#
|
30
|
-
# This can be used to make sure that all grandchildren are killed
|
31
|
-
# when the child process dies.
|
32
|
-
#
|
33
|
-
attr_accessor :leader
|
34
|
-
|
35
|
-
#
|
36
|
-
# Create a new process with the given args.
|
37
|
-
#
|
38
|
-
# @api private
|
39
|
-
# @see ChildProcess.build
|
40
|
-
#
|
41
|
-
|
42
|
-
def initialize(args)
|
43
|
-
unless args.all? { |e| e.kind_of?(String) }
|
44
|
-
raise ArgumentError, "all arguments must be String: #{args.inspect}"
|
45
|
-
end
|
46
|
-
|
47
|
-
@args = args
|
48
|
-
@started = false
|
49
|
-
@exit_code = nil
|
50
|
-
@io = nil
|
51
|
-
@cwd = nil
|
52
|
-
@detach = false
|
53
|
-
@duplex = false
|
54
|
-
@leader = false
|
55
|
-
@environment = {}
|
56
|
-
end
|
57
|
-
|
58
|
-
#
|
59
|
-
# Returns a ChildProcess::AbstractIO subclass to configure the child's IO streams.
|
60
|
-
#
|
61
|
-
|
62
|
-
def io
|
63
|
-
raise SubclassResponsibility, "io"
|
64
|
-
end
|
65
|
-
|
66
|
-
#
|
67
|
-
# @return [Integer] the pid of the process after it has started
|
68
|
-
#
|
69
|
-
|
70
|
-
def pid
|
71
|
-
raise SubclassResponsibility, "pid"
|
72
|
-
end
|
73
|
-
|
74
|
-
#
|
75
|
-
# Launch the child process
|
76
|
-
#
|
77
|
-
# @return [AbstractProcess] self
|
78
|
-
#
|
79
|
-
|
80
|
-
def start
|
81
|
-
launch_process
|
82
|
-
@started = true
|
83
|
-
|
84
|
-
self
|
85
|
-
end
|
86
|
-
|
87
|
-
#
|
88
|
-
# Forcibly terminate the process, using increasingly harsher methods if possible.
|
89
|
-
#
|
90
|
-
# @param [Integer] timeout (3) Seconds to wait before trying the next method.
|
91
|
-
#
|
92
|
-
|
93
|
-
def stop(timeout = 3)
|
94
|
-
raise SubclassResponsibility, "stop"
|
95
|
-
end
|
96
|
-
|
97
|
-
#
|
98
|
-
# Block until the process has been terminated.
|
99
|
-
#
|
100
|
-
# @return [Integer] The exit status of the process
|
101
|
-
#
|
102
|
-
|
103
|
-
def wait
|
104
|
-
raise SubclassResponsibility, "wait"
|
105
|
-
end
|
106
|
-
|
107
|
-
#
|
108
|
-
# Did the process exit?
|
109
|
-
#
|
110
|
-
# @return [Boolean]
|
111
|
-
#
|
112
|
-
|
113
|
-
def exited?
|
114
|
-
raise SubclassResponsibility, "exited?"
|
115
|
-
end
|
116
|
-
|
117
|
-
#
|
118
|
-
# Has the process started?
|
119
|
-
#
|
120
|
-
# @return [Boolean]
|
121
|
-
#
|
122
|
-
|
123
|
-
def started?
|
124
|
-
@started
|
125
|
-
end
|
126
|
-
|
127
|
-
#
|
128
|
-
# Is this process running?
|
129
|
-
#
|
130
|
-
# @return [Boolean]
|
131
|
-
#
|
132
|
-
|
133
|
-
def alive?
|
134
|
-
started? && !exited?
|
135
|
-
end
|
136
|
-
|
137
|
-
#
|
138
|
-
# Returns true if the process has exited and the exit code was not 0.
|
139
|
-
#
|
140
|
-
# @return [Boolean]
|
141
|
-
#
|
142
|
-
|
143
|
-
def crashed?
|
144
|
-
exited? && @exit_code != 0
|
145
|
-
end
|
146
|
-
|
147
|
-
#
|
148
|
-
# Wait for the process to exit, raising a ChildProcess::TimeoutError if
|
149
|
-
# the timeout expires.
|
150
|
-
#
|
151
|
-
|
152
|
-
def poll_for_exit(timeout)
|
153
|
-
log "polling #{timeout} seconds for exit"
|
154
|
-
|
155
|
-
end_time = Time.now + timeout
|
156
|
-
until (ok = exited?) || Time.now > end_time
|
157
|
-
sleep POLL_INTERVAL
|
158
|
-
end
|
159
|
-
|
160
|
-
unless ok
|
161
|
-
raise TimeoutError, "process still alive after #{timeout} seconds"
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
private
|
166
|
-
|
167
|
-
def launch_process
|
168
|
-
raise SubclassResponsibility, "launch_process"
|
169
|
-
end
|
170
|
-
|
171
|
-
def detach?
|
172
|
-
@detach
|
173
|
-
end
|
174
|
-
|
175
|
-
def duplex?
|
176
|
-
@duplex
|
177
|
-
end
|
178
|
-
|
179
|
-
def leader?
|
180
|
-
@leader
|
181
|
-
end
|
182
|
-
|
183
|
-
def log(*args)
|
184
|
-
ChildProcess.logger.debug "#{self.inspect} : #{args.inspect}"
|
185
|
-
end
|
186
|
-
|
187
|
-
def assert_started
|
188
|
-
raise Error, "process not started" unless started?
|
189
|
-
end
|
190
|
-
|
191
|
-
end # AbstractProcess
|
192
|
-
end # ChildProcess
|
1
|
+
module ChildProcess
|
2
|
+
class AbstractProcess
|
3
|
+
POLL_INTERVAL = 0.1
|
4
|
+
|
5
|
+
attr_reader :exit_code
|
6
|
+
|
7
|
+
#
|
8
|
+
# Set this to true if you do not care about when or if the process quits.
|
9
|
+
#
|
10
|
+
attr_accessor :detach
|
11
|
+
|
12
|
+
#
|
13
|
+
# Set this to true if you want to write to the process' stdin (process.io.stdin)
|
14
|
+
#
|
15
|
+
attr_accessor :duplex
|
16
|
+
|
17
|
+
#
|
18
|
+
# Modify the child's environment variables
|
19
|
+
#
|
20
|
+
attr_reader :environment
|
21
|
+
|
22
|
+
#
|
23
|
+
# Set the child's current working directory.
|
24
|
+
#
|
25
|
+
attr_accessor :cwd
|
26
|
+
|
27
|
+
#
|
28
|
+
# Set this to true to make the child process the leader of a new process group
|
29
|
+
#
|
30
|
+
# This can be used to make sure that all grandchildren are killed
|
31
|
+
# when the child process dies.
|
32
|
+
#
|
33
|
+
attr_accessor :leader
|
34
|
+
|
35
|
+
#
|
36
|
+
# Create a new process with the given args.
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
# @see ChildProcess.build
|
40
|
+
#
|
41
|
+
|
42
|
+
def initialize(args)
|
43
|
+
unless args.all? { |e| e.kind_of?(String) }
|
44
|
+
raise ArgumentError, "all arguments must be String: #{args.inspect}"
|
45
|
+
end
|
46
|
+
|
47
|
+
@args = args
|
48
|
+
@started = false
|
49
|
+
@exit_code = nil
|
50
|
+
@io = nil
|
51
|
+
@cwd = nil
|
52
|
+
@detach = false
|
53
|
+
@duplex = false
|
54
|
+
@leader = false
|
55
|
+
@environment = {}
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Returns a ChildProcess::AbstractIO subclass to configure the child's IO streams.
|
60
|
+
#
|
61
|
+
|
62
|
+
def io
|
63
|
+
raise SubclassResponsibility, "io"
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# @return [Integer] the pid of the process after it has started
|
68
|
+
#
|
69
|
+
|
70
|
+
def pid
|
71
|
+
raise SubclassResponsibility, "pid"
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Launch the child process
|
76
|
+
#
|
77
|
+
# @return [AbstractProcess] self
|
78
|
+
#
|
79
|
+
|
80
|
+
def start
|
81
|
+
launch_process
|
82
|
+
@started = true
|
83
|
+
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Forcibly terminate the process, using increasingly harsher methods if possible.
|
89
|
+
#
|
90
|
+
# @param [Integer] timeout (3) Seconds to wait before trying the next method.
|
91
|
+
#
|
92
|
+
|
93
|
+
def stop(timeout = 3)
|
94
|
+
raise SubclassResponsibility, "stop"
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Block until the process has been terminated.
|
99
|
+
#
|
100
|
+
# @return [Integer] The exit status of the process
|
101
|
+
#
|
102
|
+
|
103
|
+
def wait
|
104
|
+
raise SubclassResponsibility, "wait"
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Did the process exit?
|
109
|
+
#
|
110
|
+
# @return [Boolean]
|
111
|
+
#
|
112
|
+
|
113
|
+
def exited?
|
114
|
+
raise SubclassResponsibility, "exited?"
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Has the process started?
|
119
|
+
#
|
120
|
+
# @return [Boolean]
|
121
|
+
#
|
122
|
+
|
123
|
+
def started?
|
124
|
+
@started
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# Is this process running?
|
129
|
+
#
|
130
|
+
# @return [Boolean]
|
131
|
+
#
|
132
|
+
|
133
|
+
def alive?
|
134
|
+
started? && !exited?
|
135
|
+
end
|
136
|
+
|
137
|
+
#
|
138
|
+
# Returns true if the process has exited and the exit code was not 0.
|
139
|
+
#
|
140
|
+
# @return [Boolean]
|
141
|
+
#
|
142
|
+
|
143
|
+
def crashed?
|
144
|
+
exited? && @exit_code != 0
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Wait for the process to exit, raising a ChildProcess::TimeoutError if
|
149
|
+
# the timeout expires.
|
150
|
+
#
|
151
|
+
|
152
|
+
def poll_for_exit(timeout)
|
153
|
+
log "polling #{timeout} seconds for exit"
|
154
|
+
|
155
|
+
end_time = Time.now + timeout
|
156
|
+
until (ok = exited?) || Time.now > end_time
|
157
|
+
sleep POLL_INTERVAL
|
158
|
+
end
|
159
|
+
|
160
|
+
unless ok
|
161
|
+
raise TimeoutError, "process still alive after #{timeout} seconds"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def launch_process
|
168
|
+
raise SubclassResponsibility, "launch_process"
|
169
|
+
end
|
170
|
+
|
171
|
+
def detach?
|
172
|
+
@detach
|
173
|
+
end
|
174
|
+
|
175
|
+
def duplex?
|
176
|
+
@duplex
|
177
|
+
end
|
178
|
+
|
179
|
+
def leader?
|
180
|
+
@leader
|
181
|
+
end
|
182
|
+
|
183
|
+
def log(*args)
|
184
|
+
ChildProcess.logger.debug "#{self.inspect} : #{args.inspect}"
|
185
|
+
end
|
186
|
+
|
187
|
+
def assert_started
|
188
|
+
raise Error, "process not started" unless started?
|
189
|
+
end
|
190
|
+
|
191
|
+
end # AbstractProcess
|
192
|
+
end # ChildProcess
|
data/lib/childprocess/errors.rb
CHANGED
@@ -1,26 +1,37 @@
|
|
1
|
-
module ChildProcess
|
2
|
-
class Error < StandardError
|
3
|
-
end
|
4
|
-
|
5
|
-
class TimeoutError < Error
|
6
|
-
end
|
7
|
-
|
8
|
-
class SubclassResponsibility < Error
|
9
|
-
end
|
10
|
-
|
11
|
-
class InvalidEnvironmentVariable < Error
|
12
|
-
end
|
13
|
-
|
14
|
-
class LaunchError < Error
|
15
|
-
end
|
16
|
-
|
17
|
-
class
|
18
|
-
def initialize
|
19
|
-
message = "
|
20
|
-
"
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
1
|
+
module ChildProcess
|
2
|
+
class Error < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class TimeoutError < Error
|
6
|
+
end
|
7
|
+
|
8
|
+
class SubclassResponsibility < Error
|
9
|
+
end
|
10
|
+
|
11
|
+
class InvalidEnvironmentVariable < Error
|
12
|
+
end
|
13
|
+
|
14
|
+
class LaunchError < Error
|
15
|
+
end
|
16
|
+
|
17
|
+
class MissingFFIError < Error
|
18
|
+
def initialize
|
19
|
+
message = "FFI is a required pre-requisite for posix_spawn, falling back to default implementation. " +
|
20
|
+
"Please add it to your deployment to unlock this functionality. " +
|
21
|
+
"If you believe this is an error, please file a bug at http://github.com/enkessler/childprocess/issues"
|
22
|
+
|
23
|
+
super(message)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class MissingPlatformError < Error
|
29
|
+
def initialize
|
30
|
+
message = "posix_spawn is not yet supported on #{ChildProcess.platform_name} (#{RUBY_PLATFORM}), falling back to default implementation. " +
|
31
|
+
"If you believe this is an error, please file a bug at http://github.com/enkessler/childprocess/issues"
|
32
|
+
|
33
|
+
super(message)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -1,16 +1,16 @@
|
|
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
|
+
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
|
+
|