subprocess 1.2.0 → 1.3.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.
@@ -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: