subprocess 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -1,5 +1,4 @@
1
- Subprocess
2
- ==========
1
+ # Subprocess [![Build Status](https://travis-ci.org/stripe/subprocess.svg?branch=master)](https://travis-ci.org/stripe/subprocess)
3
2
 
4
3
  ![Jacques Cousteau Submarine](http://i.imgur.com/lmej24F.jpg)
5
4
 
@@ -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
- elsif Signal.list.respond_to?(:key)
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`. Note: we don't
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
- # Ruby 1.8's exec is really stupid--there's no way to specify that
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
- redirects = {}
345
- retained_fds.each { |fd| redirects[fd] = fd }
346
- args << redirects
274
+ retained_fds.each { |fd| options[fd] = fd }
347
275
  end
348
- exec(*args)
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 because of the FD_CLOEXEC
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
@@ -1,3 +1,3 @@
1
1
  module Subprocess
2
- VERSION = '1.2.0'
2
+ VERSION = '1.3.0'
3
3
  end
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.2.0
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: 2014-05-01 00:00:00.000000000 Z
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: 1.8.23
93
+ rubygems_version: 2.2.2
102
94
  signing_key:
103
- specification_version: 3
95
+ specification_version: 4
104
96
  summary: A port of Python's subprocess module to Ruby
105
97
  test_files: []
106
98
  has_rdoc: