subprocess 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +1 -2
- data/lib/subprocess.rb +16 -91
- data/lib/subprocess/version.rb +1 -1
- metadata +15 -23
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 82c898802f4160693d7836102254e37c303db198
|
4
|
+
data.tar.gz: 71481f1fe51f83f84be323b801674c6ae34c8723
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f3b32e75da714a7eb24ab94fa5486ed190c128b5e1e92fa8545a9797c93ff74cdef92f45a8d3e54b8d6fd653284d85d5640f6c89b926d23f9cfdd01786bbbdf3
|
7
|
+
data.tar.gz: d7d449f41f1d7c2a2201af471916bdac29696cea27058ada2454d91de7ac6543cb56715ae56393dc61b9e9c2c1a31c1fce01b7b76934d1f929909e23307324d1
|
data/README.md
CHANGED
data/lib/subprocess.rb
CHANGED
@@ -111,12 +111,9 @@ module Subprocess
|
|
111
111
|
if Signal.respond_to?(:signame)
|
112
112
|
# ruby 2.0 way
|
113
113
|
sig_name = Signal.signame(sig_num)
|
114
|
-
|
114
|
+
else
|
115
115
|
# ruby 1.9 way
|
116
116
|
sig_name = Signal.list.key(sig_num)
|
117
|
-
else
|
118
|
-
# ruby 1.8 way
|
119
|
-
sig_name = Signal.list.index(sig_num)
|
120
117
|
end
|
121
118
|
|
122
119
|
if sig_name
|
@@ -221,12 +218,11 @@ module Subprocess
|
|
221
218
|
# numbers that should not be closed before executing the child process.
|
222
219
|
# Note that, unlike Python (which has :close_fds defaulting to false), all
|
223
220
|
# file descriptors not specified here will be closed.
|
221
|
+
# @option opts [Hash] :exec_opts A hash that will be merged into the options
|
222
|
+
# hash of the call to {Kernel#exec}.
|
224
223
|
#
|
225
224
|
# @option opts [Proc] :preexec_fn A function that will be called in the
|
226
|
-
# child process immediately before executing `cmd`.
|
227
|
-
# actually close file descriptors, but instead set them to auto-close on
|
228
|
-
# `exec` (using `FD_CLOEXEC`), so your application will probably continue
|
229
|
-
# to behave as expected.
|
225
|
+
# child process immediately before executing `cmd`.
|
230
226
|
#
|
231
227
|
# @yield [process] Yields the just-spawned {Process} to the optional block.
|
232
228
|
# This occurs after all of {Process}'s error handling has been completed,
|
@@ -235,6 +231,7 @@ module Subprocess
|
|
235
231
|
# @yieldparam process [Process] The process that was just spawned.
|
236
232
|
def initialize(cmd, opts={}, &blk)
|
237
233
|
raise ArgumentError, "cmd must be an Array" unless Array === cmd
|
234
|
+
raise ArgumentError, "cmd cannot be empty" if cmd.empty?
|
238
235
|
|
239
236
|
@command = cmd
|
240
237
|
|
@@ -253,69 +250,8 @@ module Subprocess
|
|
253
250
|
|
254
251
|
@pid = fork do
|
255
252
|
begin
|
256
|
-
require 'fcntl'
|
257
|
-
|
258
253
|
FileUtils.cd(opts[:cwd]) if opts[:cwd]
|
259
254
|
|
260
|
-
# The only way to mark an fd as CLOEXEC in ruby is to create an IO
|
261
|
-
# object wrapping it. In 1.8, however, there's no way to create that
|
262
|
-
# IO without it believing it owns the underlying fd, s.t. it will
|
263
|
-
# close the fd if the IO is GC'd before the exec. Since we don't want
|
264
|
-
# that, we stash a list of these IO objects to prevent them from
|
265
|
-
# getting GC'd, since we are about to exec, which will clean
|
266
|
-
# everything up anyways.
|
267
|
-
fds = []
|
268
|
-
|
269
|
-
# We have a whole ton of file descriptors that we don't want leaking
|
270
|
-
# into the child. Set them all to close when we exec away.
|
271
|
-
#
|
272
|
-
# Ruby 1.9+ note: exec has a :close_others argument (and 2.0 closes
|
273
|
-
# FDs by default). When we stop supporting Ruby 1.8, all of this can
|
274
|
-
# go away.
|
275
|
-
if File.directory?("/dev/fd")
|
276
|
-
# On many modern UNIX-y systems, we can perform an optimization by
|
277
|
-
# looking through /dev/fd, which is a sparse listing of all the
|
278
|
-
# descriptors we have open. This allows us to avoid an expensive
|
279
|
-
# linear scan.
|
280
|
-
Dir.foreach("/dev/fd") do |file|
|
281
|
-
fd = file.to_i
|
282
|
-
if file.start_with?('.') || fd < 3 || retained_fds.include?(fd)
|
283
|
-
next
|
284
|
-
end
|
285
|
-
begin
|
286
|
-
fds << mark_fd_cloexec(fd)
|
287
|
-
rescue Errno::EBADF
|
288
|
-
# The fd might have been closed by now; that's peaceful.
|
289
|
-
end
|
290
|
-
end
|
291
|
-
else
|
292
|
-
# This is the big hammer. There's not really a good way of doing
|
293
|
-
# this comprehensively across all platforms without just trying them
|
294
|
-
# all. We only go up to the soft limit here. If you've been messing
|
295
|
-
# with the soft limit, we might miss a few. Also, on OSX (perhaps
|
296
|
-
# BSDs in general?), where the soft limit means something completely
|
297
|
-
# different.
|
298
|
-
special = [@child_stdin, @child_stdout, @child_stderr].compact
|
299
|
-
special = Hash[special.map { |f| [f.fileno, f] }]
|
300
|
-
3.upto(::Process.getrlimit(::Process::RLIMIT_NOFILE).first) do |fd|
|
301
|
-
next if retained_fds.include?(fd)
|
302
|
-
begin
|
303
|
-
# I don't know why we need to do this, but OSX started freaking
|
304
|
-
# out when trying to dup2 below if FD_CLOEXEC had been set on a
|
305
|
-
# fresh IO instance referring to the same underlying file
|
306
|
-
# descriptor as what we were trying to dup2 from.
|
307
|
-
if special[fd]
|
308
|
-
special[fd].fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
309
|
-
else
|
310
|
-
fds << mark_fd_cloexec(fd)
|
311
|
-
end
|
312
|
-
rescue Errno::EBADF # Ignore FDs that don't exist
|
313
|
-
end
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
# dup2 the correct descriptors into place. Note that this clears the
|
318
|
-
# FD_CLOEXEC flag on the new file descriptors (but not the old ones).
|
319
255
|
::STDIN.reopen(@child_stdin) if @child_stdin
|
320
256
|
::STDOUT.reopen(@child_stdout) if @child_stdout
|
321
257
|
if opts[:stderr] == STDOUT
|
@@ -333,19 +269,18 @@ module Subprocess
|
|
333
269
|
# Call the user back, maybe?
|
334
270
|
opts[:preexec_fn].call if opts[:preexec_fn]
|
335
271
|
|
336
|
-
|
337
|
-
# you want to exec a single thing *without* performing shell
|
338
|
-
# expansion. So this is the next best thing.
|
339
|
-
args = cmd
|
340
|
-
if cmd.length == 1
|
341
|
-
args = ["'" + cmd[0].gsub("'", "\\'") + "'"]
|
342
|
-
end
|
272
|
+
options = {close_others: true}.merge(opts.fetch(:exec_opts, {}))
|
343
273
|
if opts[:retain_fds]
|
344
|
-
|
345
|
-
retained_fds.each { |fd| redirects[fd] = fd }
|
346
|
-
args << redirects
|
274
|
+
retained_fds.each { |fd| options[fd] = fd }
|
347
275
|
end
|
348
|
-
|
276
|
+
|
277
|
+
# Ruby's Kernel#exec will call an exec(3) variant if called with two
|
278
|
+
# or more arguments, but when called with just a single argument will
|
279
|
+
# spawn a subshell with that argument as the command. Since we always
|
280
|
+
# want to call exec(3), we use the third exec form, which passes a
|
281
|
+
# [cmdname, argv0] array as its first argument and never invokes a
|
282
|
+
# subshell.
|
283
|
+
exec([cmd[0], cmd[0]], *cmd[1..-1], options)
|
349
284
|
|
350
285
|
rescue Exception => e
|
351
286
|
# Dump all errors up to the parent through the control socket
|
@@ -366,7 +301,7 @@ module Subprocess
|
|
366
301
|
control_w.close
|
367
302
|
|
368
303
|
# Any errors during the spawn process? We'll get past this point when the
|
369
|
-
# child execs and the OS closes control_w
|
304
|
+
# child execs and the OS closes control_w
|
370
305
|
begin
|
371
306
|
e = Marshal.load(control_r)
|
372
307
|
e = "Unknown Failure" unless e.is_a?(Exception) || e.is_a?(String)
|
@@ -547,16 +482,6 @@ module Subprocess
|
|
547
482
|
end
|
548
483
|
end
|
549
484
|
|
550
|
-
def mark_fd_cloexec(fd)
|
551
|
-
io = IO.new(fd)
|
552
|
-
io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
553
|
-
io
|
554
|
-
rescue ArgumentError => e
|
555
|
-
# Ruby maintains a self-pipe for thread interrupts, but it handles closing
|
556
|
-
# it on forks/execs
|
557
|
-
raise unless e.message == "The given fd is not accessible because RubyVM reserves it"
|
558
|
-
end
|
559
|
-
|
560
485
|
@sigchld_mutex = Mutex.new
|
561
486
|
@sigchld_fds = {}
|
562
487
|
@sigchld_old_handler = nil
|
data/lib/subprocess/version.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: subprocess
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Carl Jackson
|
@@ -13,54 +12,48 @@ authors:
|
|
13
12
|
autorequire:
|
14
13
|
bindir: bin
|
15
14
|
cert_chain: []
|
16
|
-
date:
|
15
|
+
date: 2016-06-09 00:00:00.000000000 Z
|
17
16
|
dependencies:
|
18
17
|
- !ruby/object:Gem::Dependency
|
19
18
|
name: minitest
|
20
19
|
requirement: !ruby/object:Gem::Requirement
|
21
|
-
none: false
|
22
20
|
requirements:
|
23
|
-
- - ~>
|
21
|
+
- - "~>"
|
24
22
|
- !ruby/object:Gem::Version
|
25
23
|
version: '5.0'
|
26
24
|
type: :development
|
27
25
|
prerelease: false
|
28
26
|
version_requirements: !ruby/object:Gem::Requirement
|
29
|
-
none: false
|
30
27
|
requirements:
|
31
|
-
- - ~>
|
28
|
+
- - "~>"
|
32
29
|
- !ruby/object:Gem::Version
|
33
30
|
version: '5.0'
|
34
31
|
- !ruby/object:Gem::Dependency
|
35
32
|
name: rake
|
36
33
|
requirement: !ruby/object:Gem::Requirement
|
37
|
-
none: false
|
38
34
|
requirements:
|
39
|
-
- -
|
35
|
+
- - ">="
|
40
36
|
- !ruby/object:Gem::Version
|
41
37
|
version: '0'
|
42
38
|
type: :development
|
43
39
|
prerelease: false
|
44
40
|
version_requirements: !ruby/object:Gem::Requirement
|
45
|
-
none: false
|
46
41
|
requirements:
|
47
|
-
- -
|
42
|
+
- - ">="
|
48
43
|
- !ruby/object:Gem::Version
|
49
44
|
version: '0'
|
50
45
|
- !ruby/object:Gem::Dependency
|
51
46
|
name: pry
|
52
47
|
requirement: !ruby/object:Gem::Requirement
|
53
|
-
none: false
|
54
48
|
requirements:
|
55
|
-
- -
|
49
|
+
- - ">="
|
56
50
|
- !ruby/object:Gem::Version
|
57
51
|
version: '0'
|
58
52
|
type: :development
|
59
53
|
prerelease: false
|
60
54
|
version_requirements: !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
55
|
requirements:
|
63
|
-
- -
|
56
|
+
- - ">="
|
64
57
|
- !ruby/object:Gem::Version
|
65
58
|
version: '0'
|
66
59
|
description: Control and communicate with spawned processes
|
@@ -74,33 +67,32 @@ executables: []
|
|
74
67
|
extensions: []
|
75
68
|
extra_rdoc_files: []
|
76
69
|
files:
|
77
|
-
- lib/subprocess/version.rb
|
78
|
-
- lib/subprocess.rb
|
79
70
|
- README.md
|
71
|
+
- lib/subprocess.rb
|
72
|
+
- lib/subprocess/version.rb
|
80
73
|
homepage: https://github.com/stripe/subprocess
|
81
74
|
licenses:
|
82
75
|
- MIT
|
76
|
+
metadata: {}
|
83
77
|
post_install_message:
|
84
78
|
rdoc_options: []
|
85
79
|
require_paths:
|
86
80
|
- lib
|
87
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
-
none: false
|
89
82
|
requirements:
|
90
|
-
- -
|
83
|
+
- - ">="
|
91
84
|
- !ruby/object:Gem::Version
|
92
85
|
version: '0'
|
93
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
-
none: false
|
95
87
|
requirements:
|
96
|
-
- -
|
88
|
+
- - ">="
|
97
89
|
- !ruby/object:Gem::Version
|
98
90
|
version: '0'
|
99
91
|
requirements: []
|
100
92
|
rubyforge_project:
|
101
|
-
rubygems_version:
|
93
|
+
rubygems_version: 2.2.2
|
102
94
|
signing_key:
|
103
|
-
specification_version:
|
95
|
+
specification_version: 4
|
104
96
|
summary: A port of Python's subprocess module to Ruby
|
105
97
|
test_files: []
|
106
98
|
has_rdoc:
|