childprocess 4.0.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 +11 -0
- data/Gemfile +0 -14
- data/README.md +3 -20
- data/childprocess.gemspec +1 -1
- 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 +40 -16
- data/spec/io_spec.rb +2 -2
- data/spec/spec_helper.rb +3 -18
- data/spec/unix_spec.rb +3 -7
- metadata +6 -24
- 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/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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b5d923affd397c31cc2193e6dc9d6e1a6d32e485f3721210e65caf72b9ee138
|
4
|
+
data.tar.gz: '06896c2aa64a9c521b45206d1a0638a8aa63e433a013c261909a920fab135c75'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0a5d3cfee92a6e4896eaf557dbf4fc50d54b54d42c43033776165991b1b606f12ccd1e17d0dbe26963b7d002482ee40877b3ea024765b371393e4a0cbd0343f
|
7
|
+
data.tar.gz: 6814491e59bbb30b61393670ca84d5da9d61ea5cb5dbc54a45599ef9cb7318bbf82751fddaf5c7ee5ef501718d7cad4a08636fab3a379148899af3acd0303bd4
|
@@ -0,0 +1,23 @@
|
|
1
|
+
name: CI
|
2
|
+
on: [push, pull_request]
|
3
|
+
jobs:
|
4
|
+
test:
|
5
|
+
strategy:
|
6
|
+
fail-fast: false
|
7
|
+
matrix:
|
8
|
+
os: [ ubuntu, macos, windows ]
|
9
|
+
ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', jruby, truffleruby ]
|
10
|
+
exclude:
|
11
|
+
- { os: windows, ruby: truffleruby }
|
12
|
+
# fails to load rspec: RuntimeError: CRITICAL: RUBYGEMS_ACTIVATION_MONITOR.owned?: before false -> after true
|
13
|
+
- { os: windows, ruby: jruby }
|
14
|
+
runs-on: ${{ matrix.os }}-latest
|
15
|
+
env:
|
16
|
+
CHILDPROCESS_UNSET: should-be-unset
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v2
|
19
|
+
- uses: ruby/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: ${{ matrix.ruby }}
|
22
|
+
bundler-cache: true
|
23
|
+
- run: bundle exec rake spec
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,17 @@
|
|
1
|
+
### Version 5.0.0 / 2024-01-06
|
2
|
+
|
3
|
+
* [#175](https://github.com/enkessler/childprocess/pull/175): Replace all backends by `Process.spawn` for portability, reliability and simplicity.
|
4
|
+
* [#185](https://github.com/enkessler/childprocess/pull/185): Add support for Ruby 3.x
|
5
|
+
|
6
|
+
### Version 4.1.0 / 2021-06-08
|
7
|
+
|
8
|
+
* [#170](https://github.com/enkessler/childprocess/pull/170): Update gem homepage to use `https://`
|
9
|
+
* [#177](https://github.com/enkessler/childprocess/pull/177): Add ARM64-macos support
|
10
|
+
|
1
11
|
### Version 4.0.0 / 2020-06-18
|
2
12
|
|
3
13
|
* [#167](https://github.com/enkessler/childprocess/pull/167): Fix detach behavior on Windows
|
14
|
+
* [#168](https://github.com/enkessler/childprocess/pull/168): Drop support for Ruby 2.3
|
4
15
|
|
5
16
|
### Version 3.0.0 / 2019-09-20
|
6
17
|
|
data/Gemfile
CHANGED
@@ -5,17 +5,3 @@ gemspec
|
|
5
5
|
|
6
6
|
# Used for local development/testing only
|
7
7
|
gem 'rake'
|
8
|
-
|
9
|
-
if RUBY_VERSION =~ /^1\./
|
10
|
-
gem 'tins', '< 1.7' # The 'tins' gem requires Ruby 2.x on/after this version
|
11
|
-
gem 'json', '< 2.0' # The 'json' gem drops pre-Ruby 2.x support on/after this version
|
12
|
-
gem 'term-ansicolor', '< 1.4' # The 'term-ansicolor' gem requires Ruby 2.x on/after this version
|
13
|
-
|
14
|
-
# ffi gem for Windows requires Ruby 2.x on/after this version
|
15
|
-
gem 'ffi', '< 1.9.15' if ENV['CHILDPROCESS_POSIX_SPAWN'] == 'true' || Gem.win_platform?
|
16
|
-
elsif Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2')
|
17
|
-
# Ruby 2.0/2.1 support only ffi before 1.10
|
18
|
-
gem 'ffi', '~> 1.9.0' if ENV['CHILDPROCESS_POSIX_SPAWN'] == 'true' || Gem.win_platform?
|
19
|
-
else
|
20
|
-
gem 'ffi' if ENV['CHILDPROCESS_POSIX_SPAWN'] == 'true' || Gem.win_platform?
|
21
|
-
end
|
data/README.md
CHANGED
@@ -16,8 +16,6 @@ a standalone library.
|
|
16
16
|
|
17
17
|
* Ruby 2.4+, JRuby 9+
|
18
18
|
|
19
|
-
Windows users **must** ensure the `ffi` gem (`>= 1.0.11`) is installed in order to use ChildProcess.
|
20
|
-
|
21
19
|
# Usage
|
22
20
|
|
23
21
|
The object returned from `ChildProcess.build` will implement `ChildProcess::AbstractProcess`.
|
@@ -73,9 +71,9 @@ begin
|
|
73
71
|
process = ChildProcess.build("sh" , "-c",
|
74
72
|
"for i in {1..3}; do echo $i; sleep 1; done")
|
75
73
|
process.io.stdout = w
|
76
|
-
process.start # This results in a
|
74
|
+
process.start # This results in a subprocess inheriting the write end of the pipe.
|
77
75
|
|
78
|
-
# Close parent's copy of the write end of the pipe so when the
|
76
|
+
# Close parent's copy of the write end of the pipe so when the child
|
79
77
|
# process closes its write end of the pipe the parent receives EOF when
|
80
78
|
# attempting to read from it. If the parent leaves its write end open, it
|
81
79
|
# will not detect EOF.
|
@@ -138,17 +136,6 @@ search.io.stdin.close
|
|
138
136
|
search.wait
|
139
137
|
```
|
140
138
|
|
141
|
-
#### Prefer posix_spawn on *nix
|
142
|
-
|
143
|
-
If the parent process is using a lot of memory, `fork+exec` can be very expensive. The `posix_spawn()` API removes this overhead.
|
144
|
-
|
145
|
-
```ruby
|
146
|
-
ChildProcess.posix_spawn = true
|
147
|
-
process = ChildProcess.build(*args)
|
148
|
-
```
|
149
|
-
|
150
|
-
To be able to use this, please make sure that you have the `ffi` gem installed.
|
151
|
-
|
152
139
|
### Ensure entire process tree dies
|
153
140
|
|
154
141
|
By default, the child process does not create a new process group. This means there's no guarantee that the entire process tree will die when the child process is killed. To solve this:
|
@@ -195,11 +182,7 @@ ChildProcess.logger = logger
|
|
195
182
|
|
196
183
|
# Implementation
|
197
184
|
|
198
|
-
|
199
|
-
|
200
|
-
* Unix : `fork + exec` (or `posix_spawn` if enabled)
|
201
|
-
* Windows : `CreateProcess()` and friends
|
202
|
-
* JRuby : `java.lang.{Process,ProcessBuilder}`
|
185
|
+
ChildProcess 5+ uses `Process.spawn` from the Ruby core library for maximum portability.
|
203
186
|
|
204
187
|
# Note on Patches/Pull Requests
|
205
188
|
|
data/childprocess.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Jari Bakken", "Eric Kessler", "Shane da Silva"]
|
10
10
|
s.email = ["morrow748@gmail.com", "shane@dasilva.io"]
|
11
|
-
s.homepage = "
|
11
|
+
s.homepage = "https://github.com/enkessler/childprocess"
|
12
12
|
s.summary = %q{A simple and reliable solution for controlling external programs running in the background on any Ruby / OS combination.}
|
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
|
|
data/lib/childprocess/errors.rb
CHANGED
@@ -13,25 +13,4 @@ module ChildProcess
|
|
13
13
|
|
14
14
|
class LaunchError < Error
|
15
15
|
end
|
16
|
-
|
17
|
-
class MissingFFIError < Error
|
18
|
-
def initialize
|
19
|
-
message = "FFI is a required pre-requisite for Windows or posix_spawn support in the ChildProcess gem. " +
|
20
|
-
"Ensure the `ffi` gem is installed. " +
|
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
16
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require_relative 'abstract_process'
|
2
|
+
|
3
|
+
module ChildProcess
|
4
|
+
class ProcessSpawnProcess < AbstractProcess
|
5
|
+
attr_reader :pid
|
6
|
+
|
7
|
+
def exited?
|
8
|
+
return true if @exit_code
|
9
|
+
|
10
|
+
assert_started
|
11
|
+
pid, status = ::Process.waitpid2(@pid, ::Process::WNOHANG | ::Process::WUNTRACED)
|
12
|
+
pid = nil if pid == 0 # may happen on jruby
|
13
|
+
|
14
|
+
log(:pid => pid, :status => status)
|
15
|
+
|
16
|
+
if pid
|
17
|
+
set_exit_code(status)
|
18
|
+
end
|
19
|
+
|
20
|
+
!!pid
|
21
|
+
rescue Errno::ECHILD
|
22
|
+
# may be thrown for detached processes
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
def wait
|
27
|
+
assert_started
|
28
|
+
|
29
|
+
if exited?
|
30
|
+
exit_code
|
31
|
+
else
|
32
|
+
_, status = ::Process.waitpid2(@pid)
|
33
|
+
|
34
|
+
set_exit_code(status)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def launch_process
|
41
|
+
environment = {}
|
42
|
+
@environment.each_pair do |key, value|
|
43
|
+
key = key.to_s
|
44
|
+
value = value.nil? ? nil : value.to_s
|
45
|
+
|
46
|
+
if key.include?("\0") || key.include?("=") || value.to_s.include?("\0")
|
47
|
+
raise InvalidEnvironmentVariable, "#{key.inspect} => #{value.to_s.inspect}"
|
48
|
+
end
|
49
|
+
environment[key] = value
|
50
|
+
end
|
51
|
+
|
52
|
+
options = {}
|
53
|
+
|
54
|
+
options[:out] = io.stdout ? io.stdout.fileno : File::NULL
|
55
|
+
options[:err] = io.stderr ? io.stderr.fileno : File::NULL
|
56
|
+
|
57
|
+
if duplex?
|
58
|
+
reader, writer = ::IO.pipe
|
59
|
+
options[:in] = reader.fileno
|
60
|
+
unless ChildProcess.windows?
|
61
|
+
options[writer.fileno] = :close
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
if leader?
|
66
|
+
if ChildProcess.windows?
|
67
|
+
options[:new_pgroup] = true
|
68
|
+
else
|
69
|
+
options[:pgroup] = true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
options[:chdir] = @cwd if @cwd
|
74
|
+
|
75
|
+
if @args.size == 1
|
76
|
+
# When given a single String, Process.spawn would think it should use the shell
|
77
|
+
# if there is any special character in it. However, ChildProcess should never
|
78
|
+
# use the shell. So we use the [cmdname, argv0] form to force no shell.
|
79
|
+
arg = @args[0]
|
80
|
+
args = [[arg, arg]]
|
81
|
+
else
|
82
|
+
args = @args
|
83
|
+
end
|
84
|
+
|
85
|
+
begin
|
86
|
+
@pid = ::Process.spawn(environment, *args, options)
|
87
|
+
rescue SystemCallError => e
|
88
|
+
raise LaunchError, e.message
|
89
|
+
end
|
90
|
+
|
91
|
+
if duplex?
|
92
|
+
io._stdin = writer
|
93
|
+
reader.close
|
94
|
+
end
|
95
|
+
|
96
|
+
::Process.detach(@pid) if detach?
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_exit_code(status)
|
100
|
+
@exit_code = status.exitstatus || status.termsig
|
101
|
+
end
|
102
|
+
|
103
|
+
def send_term
|
104
|
+
send_signal 'TERM'
|
105
|
+
end
|
106
|
+
|
107
|
+
def send_kill
|
108
|
+
send_signal 'KILL'
|
109
|
+
end
|
110
|
+
|
111
|
+
def send_signal(sig)
|
112
|
+
assert_started
|
113
|
+
|
114
|
+
log "sending #{sig}"
|
115
|
+
if leader?
|
116
|
+
if ChildProcess.unix?
|
117
|
+
::Process.kill sig, -@pid # negative pid == process group
|
118
|
+
else
|
119
|
+
output = `taskkill /F /T /PID #{@pid}`
|
120
|
+
log output
|
121
|
+
end
|
122
|
+
else
|
123
|
+
::Process.kill sig, @pid
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
+
require_relative '../process_spawn_process'
|
2
|
+
|
1
3
|
module ChildProcess
|
2
4
|
module Unix
|
3
|
-
class Process <
|
4
|
-
attr_reader :pid
|
5
|
-
|
5
|
+
class Process < ProcessSpawnProcess
|
6
6
|
def io
|
7
7
|
@io ||= Unix::IO.new
|
8
8
|
end
|
@@ -24,67 +24,6 @@ module ChildProcess
|
|
24
24
|
# and send_kill
|
25
25
|
true
|
26
26
|
end
|
27
|
-
|
28
|
-
def exited?
|
29
|
-
return true if @exit_code
|
30
|
-
|
31
|
-
assert_started
|
32
|
-
pid, status = ::Process.waitpid2(@pid, ::Process::WNOHANG | ::Process::WUNTRACED)
|
33
|
-
pid = nil if pid == 0 # may happen on jruby
|
34
|
-
|
35
|
-
log(:pid => pid, :status => status)
|
36
|
-
|
37
|
-
if pid
|
38
|
-
set_exit_code(status)
|
39
|
-
end
|
40
|
-
|
41
|
-
!!pid
|
42
|
-
rescue Errno::ECHILD
|
43
|
-
# may be thrown for detached processes
|
44
|
-
true
|
45
|
-
end
|
46
|
-
|
47
|
-
def wait
|
48
|
-
assert_started
|
49
|
-
|
50
|
-
if exited?
|
51
|
-
exit_code
|
52
|
-
else
|
53
|
-
_, status = ::Process.waitpid2(@pid)
|
54
|
-
|
55
|
-
set_exit_code(status)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def send_term
|
62
|
-
send_signal 'TERM'
|
63
|
-
end
|
64
|
-
|
65
|
-
def send_kill
|
66
|
-
send_signal 'KILL'
|
67
|
-
end
|
68
|
-
|
69
|
-
def send_signal(sig)
|
70
|
-
assert_started
|
71
|
-
|
72
|
-
log "sending #{sig}"
|
73
|
-
::Process.kill sig, _pid
|
74
|
-
end
|
75
|
-
|
76
|
-
def set_exit_code(status)
|
77
|
-
@exit_code = status.exitstatus || status.termsig
|
78
|
-
end
|
79
|
-
|
80
|
-
def _pid
|
81
|
-
if leader?
|
82
|
-
-@pid # negative pid == process group
|
83
|
-
else
|
84
|
-
@pid
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
27
|
end # Process
|
89
28
|
end # Unix
|
90
29
|
end # ChildProcess
|
data/lib/childprocess/unix.rb
CHANGED
@@ -3,7 +3,5 @@ module ChildProcess
|
|
3
3
|
end
|
4
4
|
end
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
require "childprocess/unix/fork_exec_process"
|
9
|
-
# PosixSpawnProcess + ffi is required on demand.
|
6
|
+
require_relative "unix/io"
|
7
|
+
require_relative "unix/process"
|
data/lib/childprocess/version.rb
CHANGED
@@ -1,131 +1,28 @@
|
|
1
|
+
require_relative '../process_spawn_process'
|
2
|
+
|
1
3
|
module ChildProcess
|
2
4
|
module Windows
|
3
|
-
class Process <
|
4
|
-
|
5
|
-
attr_reader :pid
|
6
|
-
|
5
|
+
class Process < ProcessSpawnProcess
|
7
6
|
def io
|
8
7
|
@io ||= Windows::IO.new
|
9
8
|
end
|
10
9
|
|
11
10
|
def stop(timeout = 3)
|
12
11
|
assert_started
|
12
|
+
send_kill
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
ensure
|
19
|
-
close_handle
|
20
|
-
close_job_if_necessary
|
21
|
-
end
|
22
|
-
|
23
|
-
def wait
|
24
|
-
if exited?
|
25
|
-
exit_code
|
26
|
-
else
|
27
|
-
@handle.wait
|
28
|
-
@exit_code = @handle.exit_code
|
29
|
-
|
30
|
-
close_handle
|
31
|
-
close_job_if_necessary
|
32
|
-
|
33
|
-
@exit_code
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def exited?
|
38
|
-
return true if @exit_code
|
39
|
-
assert_started
|
40
|
-
|
41
|
-
code = @handle.exit_code
|
42
|
-
exited = code != PROCESS_STILL_ACTIVE
|
43
|
-
|
44
|
-
log(:exited? => exited, :code => code)
|
45
|
-
|
46
|
-
if exited
|
47
|
-
@exit_code = code
|
48
|
-
close_handle
|
49
|
-
close_job_if_necessary
|
50
|
-
end
|
51
|
-
|
52
|
-
exited
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def launch_process
|
58
|
-
builder = ProcessBuilder.new(@args)
|
59
|
-
builder.leader = leader?
|
60
|
-
builder.detach = detach?
|
61
|
-
builder.duplex = duplex?
|
62
|
-
builder.environment = @environment unless @environment.empty?
|
63
|
-
builder.cwd = @cwd
|
64
|
-
|
65
|
-
if @io
|
66
|
-
builder.stdout = @io.stdout
|
67
|
-
builder.stderr = @io.stderr
|
68
|
-
end
|
69
|
-
|
70
|
-
@pid = builder.start
|
71
|
-
@handle = Handle.open @pid
|
72
|
-
|
73
|
-
if leader?
|
74
|
-
@job = Job.new(detach?, true)
|
75
|
-
@job << @handle
|
76
|
-
end
|
77
|
-
|
78
|
-
if duplex?
|
79
|
-
raise Error, "no stdin stream" unless builder.stdin
|
80
|
-
io._stdin = builder.stdin
|
81
|
-
end
|
82
|
-
|
83
|
-
self
|
84
|
-
end
|
85
|
-
|
86
|
-
def close_handle
|
87
|
-
@handle.close
|
88
|
-
end
|
89
|
-
|
90
|
-
def close_job_if_necessary
|
91
|
-
@job.close if leader?
|
92
|
-
end
|
93
|
-
|
94
|
-
|
95
|
-
class Job
|
96
|
-
def initialize(detach, leader)
|
97
|
-
@pointer = Lib.create_job_object(nil, nil)
|
98
|
-
|
99
|
-
if @pointer.nil? || @pointer.null?
|
100
|
-
raise Error, "unable to create job object"
|
101
|
-
end
|
102
|
-
|
103
|
-
basic = JobObjectBasicLimitInformation.new
|
104
|
-
basic[:LimitFlags] |= JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE if !detach
|
105
|
-
basic[:LimitFlags] |= JOB_OBJECT_LIMIT_BREAKAWAY_OK if leader
|
106
|
-
|
107
|
-
extended = JobObjectExtendedLimitInformation.new
|
108
|
-
extended[:BasicLimitInformation] = basic
|
109
|
-
|
110
|
-
ret = Lib.set_information_job_object(
|
111
|
-
@pointer,
|
112
|
-
JOB_OBJECT_EXTENDED_LIMIT_INFORMATION,
|
113
|
-
extended,
|
114
|
-
extended.size
|
115
|
-
)
|
116
|
-
|
117
|
-
Lib.check_error ret
|
118
|
-
end
|
119
|
-
|
120
|
-
def <<(handle)
|
121
|
-
Lib.check_error Lib.assign_process_to_job_object(@pointer, handle.pointer)
|
14
|
+
begin
|
15
|
+
return poll_for_exit(timeout)
|
16
|
+
rescue TimeoutError
|
17
|
+
# try next
|
122
18
|
end
|
123
19
|
|
124
|
-
|
125
|
-
|
126
|
-
|
20
|
+
wait
|
21
|
+
rescue Errno::ECHILD, Errno::ESRCH
|
22
|
+
# handle race condition where process dies between timeout
|
23
|
+
# and send_kill
|
24
|
+
true
|
127
25
|
end
|
128
|
-
|
129
26
|
end # Process
|
130
27
|
end # Windows
|
131
28
|
end # ChildProcess
|
data/lib/childprocess/windows.rb
CHANGED
@@ -1,38 +1,9 @@
|
|
1
1
|
require "rbconfig"
|
2
2
|
|
3
|
-
begin
|
4
|
-
require 'ffi'
|
5
|
-
rescue LoadError
|
6
|
-
raise ChildProcess::MissingFFIError
|
7
|
-
end
|
8
|
-
|
9
3
|
module ChildProcess
|
10
4
|
module Windows
|
11
|
-
module Lib
|
12
|
-
extend FFI::Library
|
13
|
-
|
14
|
-
def self.msvcrt_name
|
15
|
-
host_part = RbConfig::CONFIG['host_os'].split("_")[1]
|
16
|
-
manifest = File.join(RbConfig::CONFIG['bindir'], 'ruby.exe.manifest')
|
17
|
-
|
18
|
-
if host_part && host_part.to_i > 80 && File.exists?(manifest)
|
19
|
-
"msvcr#{host_part}"
|
20
|
-
else
|
21
|
-
"msvcrt"
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
ffi_lib "kernel32", msvcrt_name
|
26
|
-
ffi_convention :stdcall
|
27
|
-
|
28
|
-
|
29
|
-
end # Library
|
30
5
|
end # Windows
|
31
6
|
end # ChildProcess
|
32
7
|
|
33
|
-
require "childprocess/windows/lib"
|
34
|
-
require "childprocess/windows/structs"
|
35
|
-
require "childprocess/windows/handle"
|
36
8
|
require "childprocess/windows/io"
|
37
|
-
require "childprocess/windows/process_builder"
|
38
9
|
require "childprocess/windows/process"
|