posix-spawn 0.3.10 → 0.3.15
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/.travis.yml +9 -0
- data/COPYING +0 -6
- data/Rakefile +7 -1
- data/ext/posix-spawn.c +32 -27
- data/lib/posix/spawn.rb +5 -5
- data/lib/posix/spawn/child.rb +20 -6
- data/lib/posix/spawn/version.rb +1 -1
- data/posix-spawn.gemspec +1 -1
- data/test/test_child.rb +97 -20
- data/test/test_spawn.rb +1 -1
- metadata +4 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e80888255d57122ba2ad477c456582e0ebfdd05a61b175c60577ee8b38e579ad
|
4
|
+
data.tar.gz: 12d37e71310f0127b75b0f31da196c9c7554cac29a31d63754583f7737132190
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3371e197b9b63ec2dce0b64d070bce8628ccb63112bcd14e8f7426891d1acf4d4ce4bc9558f44a832eaabd194b4b11a7feb2f12db2dd1d6db60968b8b9bc1a2a
|
7
|
+
data.tar.gz: 4d63126f9866a66ac6cc50d811be076939e1048f490aa40c55db1931398e016d225c3ae3da939a93646be551e6b207066f1dd4d2a1ee4f7dfe859a4404325242
|
data/.travis.yml
ADDED
data/COPYING
CHANGED
@@ -20,9 +20,3 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
20
20
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
21
21
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
22
|
SOFTWARE.
|
23
|
-
|
24
|
-
A small portion of the environ dup'ing code in ext/posix-spawn.c
|
25
|
-
was taken from glibc <http://www.gnu.org/s/libc/> and is maybe
|
26
|
-
Copyright (c) 2011 by The Free Software Foundation or maybe
|
27
|
-
by others mentioned in the glibc LICENSES file. glibc is
|
28
|
-
distributed under the terms of the LGPL license.
|
data/Rakefile
CHANGED
@@ -14,7 +14,13 @@ end
|
|
14
14
|
# Ruby Extension
|
15
15
|
# ==========================================================
|
16
16
|
|
17
|
-
|
17
|
+
begin
|
18
|
+
require 'rake/extensiontask'
|
19
|
+
rescue LoadError => boom
|
20
|
+
warn "ERROR: The rake-compiler gem dependency is missing."
|
21
|
+
warn "Please run `bundle install' and try again."
|
22
|
+
raise
|
23
|
+
end
|
18
24
|
Rake::ExtensionTask.new('posix_spawn_ext', GEMSPEC) do |ext|
|
19
25
|
ext.ext_dir = 'ext'
|
20
26
|
end
|
data/ext/posix-spawn.c
CHANGED
@@ -45,7 +45,7 @@ static VALUE rb_mPOSIXSpawn;
|
|
45
45
|
* an actual fd number:
|
46
46
|
* - The symbols :in, :out, or :err for fds 0, 1, or 2.
|
47
47
|
* - An IO object. (IO#fileno is returned)
|
48
|
-
* -
|
48
|
+
* - An Integer.
|
49
49
|
*
|
50
50
|
* Returns the fd number >= 0 if one could be established, or -1 if the object
|
51
51
|
* does not map to an fd.
|
@@ -56,7 +56,11 @@ posixspawn_obj_to_fd(VALUE obj)
|
|
56
56
|
int fd = -1;
|
57
57
|
switch (TYPE(obj)) {
|
58
58
|
case T_FIXNUM:
|
59
|
-
|
59
|
+
case T_BIGNUM:
|
60
|
+
/* Integer fd number
|
61
|
+
* rb_fix2int takes care of raising if the provided object is a
|
62
|
+
* Bignum and is out of range of an int
|
63
|
+
*/
|
60
64
|
fd = FIX2INT(obj);
|
61
65
|
break;
|
62
66
|
|
@@ -94,7 +98,7 @@ posixspawn_obj_to_fd(VALUE obj)
|
|
94
98
|
/*
|
95
99
|
* Hash iterator that sets up the posix_spawn_file_actions_t with addclose
|
96
100
|
* operations. Only hash pairs whose value is :close are processed. Keys may
|
97
|
-
* be the :in, :out, :err, an IO object, or
|
101
|
+
* be the :in, :out, :err, an IO object, or an Integer fd number.
|
98
102
|
*
|
99
103
|
* Returns ST_DELETE when an addclose operation was added; ST_CONTINUE when
|
100
104
|
* no operation was performed.
|
@@ -269,27 +273,27 @@ each_env_check_i(VALUE key, VALUE val, VALUE arg)
|
|
269
273
|
static int
|
270
274
|
each_env_i(VALUE key, VALUE val, VALUE arg)
|
271
275
|
{
|
272
|
-
char *name = StringValuePtr(key);
|
273
|
-
size_t
|
276
|
+
const char *name = StringValuePtr(key);
|
277
|
+
const size_t name_len = strlen(name);
|
274
278
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
if (!
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
279
|
+
char **envp = (char **)arg;
|
280
|
+
size_t i, j;
|
281
|
+
|
282
|
+
for (i = 0; envp[i];) {
|
283
|
+
const char *ev = envp[i];
|
284
|
+
|
285
|
+
if (strlen(ev) > name_len && !memcmp(ev, name, name_len) && ev[name_len] == '=') {
|
286
|
+
/* This operates on a duplicated environment -- release the
|
287
|
+
* existing entry memory before shifting the subsequent entry
|
288
|
+
* pointers down. */
|
289
|
+
free(envp[i]);
|
290
|
+
|
291
|
+
for (j = i; envp[j]; ++j)
|
292
|
+
envp[j] = envp[j + 1];
|
293
|
+
continue;
|
290
294
|
}
|
291
|
-
|
292
|
-
|
295
|
+
i++;
|
296
|
+
}
|
293
297
|
|
294
298
|
/*
|
295
299
|
* Insert the new value if we have one. We can assume there is space
|
@@ -301,15 +305,15 @@ each_env_i(VALUE key, VALUE val, VALUE arg)
|
|
301
305
|
char *cval = StringValuePtr(val);
|
302
306
|
|
303
307
|
size_t cval_len = strlen(cval);
|
304
|
-
size_t ep_len =
|
308
|
+
size_t ep_len = name_len + 1 + cval_len + 1; /* +2 for null terminator and '=' separator */
|
305
309
|
|
306
310
|
/* find the last entry */
|
307
311
|
while (*ep != NULL) ++ep;
|
308
312
|
*ep = malloc(ep_len);
|
309
313
|
|
310
|
-
strncpy(*ep, name,
|
311
|
-
(*ep)[
|
312
|
-
strncpy(*ep +
|
314
|
+
strncpy(*ep, name, name_len);
|
315
|
+
(*ep)[name_len] = '=';
|
316
|
+
strncpy(*ep + name_len + 1, cval, cval_len);
|
313
317
|
(*ep)[ep_len-1] = 0;
|
314
318
|
}
|
315
319
|
|
@@ -373,6 +377,7 @@ rb_posixspawn_pspawn(VALUE self, VALUE env, VALUE argv, VALUE options)
|
|
373
377
|
|
374
378
|
if (RHASH_SIZE(env) > 0) {
|
375
379
|
int size = 0;
|
380
|
+
char **new_env;
|
376
381
|
|
377
382
|
char **curr = environ;
|
378
383
|
if (curr) {
|
@@ -387,7 +392,7 @@ rb_posixspawn_pspawn(VALUE self, VALUE env, VALUE argv, VALUE options)
|
|
387
392
|
size = 0;
|
388
393
|
}
|
389
394
|
|
390
|
-
|
395
|
+
new_env = calloc(size+RHASH_SIZE(env)+1, sizeof(char*));
|
391
396
|
for (i = 0; i < size; i++) {
|
392
397
|
new_env[i] = strdup(environ[i]);
|
393
398
|
}
|
data/lib/posix/spawn.rb
CHANGED
@@ -85,7 +85,7 @@ module POSIX
|
|
85
85
|
#
|
86
86
|
# spawn(command, :chdir => "/var/tmp")
|
87
87
|
#
|
88
|
-
# The :in, :out, :err,
|
88
|
+
# The :in, :out, :err, an Integer, an IO object or an Array option specify
|
89
89
|
# fd redirection. For example, stderr can be merged into stdout as follows:
|
90
90
|
#
|
91
91
|
# spawn(command, :err => :out)
|
@@ -460,11 +460,11 @@ module POSIX
|
|
460
460
|
|
461
461
|
# Determine whether object is fd-like.
|
462
462
|
#
|
463
|
-
# Returns true if object is an instance of IO,
|
463
|
+
# Returns true if object is an instance of IO, Integer >= 0, or one of the
|
464
464
|
# the symbolic names :in, :out, or :err.
|
465
465
|
def fd?(object)
|
466
466
|
case object
|
467
|
-
when
|
467
|
+
when Integer
|
468
468
|
object >= 0
|
469
469
|
when :in, :out, :err, STDIN, STDOUT, STDERR, $stdin, $stdout, $stderr, IO
|
470
470
|
true
|
@@ -486,7 +486,7 @@ module POSIX
|
|
486
486
|
STDOUT
|
487
487
|
when :err, 2
|
488
488
|
STDERR
|
489
|
-
when
|
489
|
+
when Integer
|
490
490
|
object >= 0 ? IO.for_fd(object) : nil
|
491
491
|
when IO
|
492
492
|
object
|
@@ -529,7 +529,7 @@ module POSIX
|
|
529
529
|
#
|
530
530
|
# Returns a [[cmdname, argv0], argv1, ...] array.
|
531
531
|
def adjust_process_spawn_argv(args)
|
532
|
-
if args.size == 1 && args[0] =~ /[ |>]/
|
532
|
+
if args.size == 1 && args[0].is_a?(String) && args[0] =~ /[ |>]/
|
533
533
|
# single string with these characters means run it through the shell
|
534
534
|
command_and_args = system_command_prefixes + [args[0]]
|
535
535
|
[*command_and_args]
|
data/lib/posix/spawn/child.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'posix/spawn'
|
2
|
-
|
3
1
|
module POSIX
|
4
2
|
module Spawn
|
5
3
|
# POSIX::Spawn::Child includes logic for executing child processes and
|
@@ -77,6 +75,9 @@ module POSIX
|
|
77
75
|
# :max => total Maximum number of bytes of output to allow the
|
78
76
|
# process to generate before aborting with a
|
79
77
|
# MaximumOutputExceeded exception.
|
78
|
+
# :pgroup_kill => bool Boolean specifying whether to kill the process
|
79
|
+
# group (true) or individual process (false, default).
|
80
|
+
# Setting this option true implies :pgroup => true.
|
80
81
|
#
|
81
82
|
# Returns a new Child instance whose underlying process has already
|
82
83
|
# executed to completion. The out, err, and status attributes are
|
@@ -87,6 +88,10 @@ module POSIX
|
|
87
88
|
@input = @options.delete(:input)
|
88
89
|
@timeout = @options.delete(:timeout)
|
89
90
|
@max = @options.delete(:max)
|
91
|
+
if @options.delete(:pgroup_kill)
|
92
|
+
@pgroup_kill = true
|
93
|
+
@options[:pgroup] = true
|
94
|
+
end
|
90
95
|
@options.delete(:chdir) if @options[:chdir].nil?
|
91
96
|
exec! if !@options.delete(:noexec)
|
92
97
|
end
|
@@ -128,6 +133,11 @@ module POSIX
|
|
128
133
|
# Total command execution time (wall-clock time)
|
129
134
|
attr_reader :runtime
|
130
135
|
|
136
|
+
# The pid of the spawned child process. This is unlikely to be a valid
|
137
|
+
# current pid since Child#exec! doesn't return until the process finishes
|
138
|
+
# and is reaped.
|
139
|
+
attr_reader :pid
|
140
|
+
|
131
141
|
# Determine if the process did exit with a zero exit status.
|
132
142
|
def success?
|
133
143
|
@status && @status.success?
|
@@ -139,17 +149,22 @@ module POSIX
|
|
139
149
|
def exec!
|
140
150
|
# spawn the process and hook up the pipes
|
141
151
|
pid, stdin, stdout, stderr = popen4(@env, *(@argv + [@options]))
|
152
|
+
@pid = pid
|
142
153
|
|
143
154
|
# async read from all streams into buffers
|
144
155
|
read_and_write(@input, stdin, stdout, stderr, @timeout, @max)
|
145
156
|
|
146
157
|
# grab exit status
|
147
158
|
@status = waitpid(pid)
|
148
|
-
rescue Object
|
159
|
+
rescue Object
|
149
160
|
[stdin, stdout, stderr].each { |fd| fd.close rescue nil }
|
150
161
|
if @status.nil?
|
151
|
-
|
152
|
-
|
162
|
+
if !@pgroup_kill
|
163
|
+
::Process.kill('TERM', pid) rescue nil
|
164
|
+
else
|
165
|
+
::Process.kill('-TERM', pid) rescue nil
|
166
|
+
end
|
167
|
+
@status = waitpid(pid) rescue nil
|
153
168
|
end
|
154
169
|
raise
|
155
170
|
ensure
|
@@ -180,7 +195,6 @@ module POSIX
|
|
180
195
|
def read_and_write(input, stdin, stdout, stderr, timeout=nil, max=nil)
|
181
196
|
max = nil if max && max <= 0
|
182
197
|
@out, @err = '', ''
|
183
|
-
offset = 0
|
184
198
|
|
185
199
|
# force all string and IO encodings to BINARY under 1.9 for now
|
186
200
|
if @out.respond_to?(:force_encoding) and stdin.respond_to?(:set_encoding)
|
data/lib/posix/spawn/version.rb
CHANGED
data/posix-spawn.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
|
12
12
|
s.authors = ['Ryan Tomayko', 'Aman Gupta']
|
13
13
|
s.email = ['r@tomayko.com', 'aman@tmm1.net']
|
14
|
-
s.licenses = ['MIT'
|
14
|
+
s.licenses = ['MIT']
|
15
15
|
|
16
16
|
s.add_development_dependency 'rake-compiler', '0.7.6'
|
17
17
|
s.add_development_dependency 'minitest', '>= 4'
|
data/test/test_child.rb
CHANGED
@@ -1,10 +1,42 @@
|
|
1
1
|
# coding: UTF-8
|
2
|
-
|
3
2
|
require 'test_helper'
|
4
3
|
|
5
4
|
class ChildTest < Minitest::Test
|
6
5
|
include POSIX::Spawn
|
7
6
|
|
7
|
+
# Become a new process group.
|
8
|
+
def setup
|
9
|
+
Process.setpgrp
|
10
|
+
end
|
11
|
+
|
12
|
+
# Kill any orphaned processes in our process group before continuing but
|
13
|
+
# ignore the TERM signal we receive.
|
14
|
+
def teardown
|
15
|
+
trap("TERM") { trap("TERM", "DEFAULT") }
|
16
|
+
begin
|
17
|
+
Process.kill("-TERM", Process.pid)
|
18
|
+
Process.wait
|
19
|
+
rescue Errno::ECHILD
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# verify the process is no longer running and has been reaped.
|
24
|
+
def assert_process_reaped(pid)
|
25
|
+
Process.kill(0, pid)
|
26
|
+
assert false, "Process #{pid} still running"
|
27
|
+
rescue Errno::ESRCH
|
28
|
+
end
|
29
|
+
|
30
|
+
# verifies that all processes in the given process group are no longer running
|
31
|
+
# and have been reaped. The current ruby test process is excluded.
|
32
|
+
# XXX It's weird to use the SUT here but the :pgroup option is useful. Could
|
33
|
+
# be a IO.popen under Ruby >= 1.9 since it also supports :pgroup.
|
34
|
+
def assert_process_group_reaped(pgid)
|
35
|
+
command = "ps axo pgid,pid,args | grep '^#{pgid} ' | grep -v '^#{pgid} #$$'"
|
36
|
+
procs = POSIX::Spawn::Child.new(command, :pgroup => true).out
|
37
|
+
assert procs.empty?, "Processes in group #{pgid} still running:\n#{procs}"
|
38
|
+
end
|
39
|
+
|
8
40
|
def test_sanity
|
9
41
|
assert_same POSIX::Spawn::Child, Child
|
10
42
|
end
|
@@ -56,21 +88,45 @@ class ChildTest < Minitest::Test
|
|
56
88
|
end
|
57
89
|
|
58
90
|
def test_max
|
59
|
-
|
60
|
-
|
61
|
-
|
91
|
+
child = Child.build('yes', :max => 100_000)
|
92
|
+
assert_raises(MaximumOutputExceeded) { child.exec! }
|
93
|
+
assert_process_reaped child.pid
|
94
|
+
assert_process_group_reaped Process.pid
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_max_pgroup_kill
|
98
|
+
child = Child.build('yes', :max => 100_000, :pgroup_kill => true)
|
99
|
+
assert_raises(MaximumOutputExceeded) { child.exec! }
|
100
|
+
assert_process_reaped child.pid
|
101
|
+
assert_process_group_reaped child.pid
|
62
102
|
end
|
63
103
|
|
64
104
|
def test_max_with_child_hierarchy
|
65
|
-
|
66
|
-
|
67
|
-
|
105
|
+
child = Child.build('/bin/sh', '-c', 'true && yes', :max => 100_000)
|
106
|
+
assert_raises(MaximumOutputExceeded) { child.exec! }
|
107
|
+
assert_process_reaped child.pid
|
108
|
+
assert_process_group_reaped Process.pid
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_max_with_child_hierarchy_pgroup_kill
|
112
|
+
child = Child.build('/bin/sh', '-c', 'true && yes', :max => 100_000, :pgroup_kill => true)
|
113
|
+
assert_raises(MaximumOutputExceeded) { child.exec! }
|
114
|
+
assert_process_reaped child.pid
|
115
|
+
assert_process_group_reaped child.pid
|
68
116
|
end
|
69
117
|
|
70
118
|
def test_max_with_stubborn_child
|
71
|
-
|
72
|
-
|
73
|
-
|
119
|
+
child = Child.build("trap '' TERM; yes", :max => 100_000)
|
120
|
+
assert_raises(MaximumOutputExceeded) { child.exec! }
|
121
|
+
assert_process_reaped child.pid
|
122
|
+
assert_process_group_reaped Process.pid
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_max_with_stubborn_child_pgroup_kill
|
126
|
+
child = Child.build("trap '' TERM; yes", :max => 100_000, :pgroup_kill => true)
|
127
|
+
assert_raises(MaximumOutputExceeded) { child.exec! }
|
128
|
+
assert_process_reaped child.pid
|
129
|
+
assert_process_group_reaped child.pid
|
74
130
|
end
|
75
131
|
|
76
132
|
def test_max_with_partial_output
|
@@ -80,6 +136,8 @@ class ChildTest < Minitest::Test
|
|
80
136
|
p.exec!
|
81
137
|
end
|
82
138
|
assert_output_exceeds_repeated_string("y\n", 100_000, p.out)
|
139
|
+
assert_process_reaped p.pid
|
140
|
+
assert_process_group_reaped Process.pid
|
83
141
|
end
|
84
142
|
|
85
143
|
def test_max_with_partial_output_long_lines
|
@@ -88,28 +146,47 @@ class ChildTest < Minitest::Test
|
|
88
146
|
p.exec!
|
89
147
|
end
|
90
148
|
assert_output_exceeds_repeated_string("nice to meet you\n", 10_000, p.out)
|
149
|
+
assert_process_reaped p.pid
|
150
|
+
assert_process_group_reaped Process.pid
|
91
151
|
end
|
92
152
|
|
93
153
|
def test_timeout
|
94
154
|
start = Time.now
|
95
|
-
|
96
|
-
|
97
|
-
|
155
|
+
child = Child.build('sleep', '1', :timeout => 0.05)
|
156
|
+
assert_raises(TimeoutExceeded) { child.exec! }
|
157
|
+
assert_process_reaped child.pid
|
158
|
+
assert_process_group_reaped Process.pid
|
159
|
+
assert (Time.now-start) <= 0.2
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_timeout_pgroup_kill
|
163
|
+
start = Time.now
|
164
|
+
child = Child.build('sleep', '1', :timeout => 0.05, :pgroup_kill => true)
|
165
|
+
assert_raises(TimeoutExceeded) { child.exec! }
|
166
|
+
assert_process_reaped child.pid
|
167
|
+
assert_process_group_reaped child.pid
|
98
168
|
assert (Time.now-start) <= 0.2
|
99
169
|
end
|
100
170
|
|
101
171
|
def test_timeout_with_child_hierarchy
|
102
|
-
|
103
|
-
|
104
|
-
|
172
|
+
child = Child.build('/bin/sh', '-c', 'true && sleep 1', :timeout => 0.05)
|
173
|
+
assert_raises(TimeoutExceeded) { child.exec! }
|
174
|
+
assert_process_reaped child.pid
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_timeout_with_child_hierarchy_pgroup_kill
|
178
|
+
child = Child.build('/bin/sh', '-c', 'true && sleep 1', :timeout => 0.05, :pgroup_kill => true)
|
179
|
+
assert_raises(TimeoutExceeded) { child.exec! }
|
180
|
+
assert_process_reaped child.pid
|
181
|
+
assert_process_group_reaped child.pid
|
105
182
|
end
|
106
183
|
|
107
184
|
def test_timeout_with_partial_output
|
108
185
|
start = Time.now
|
109
|
-
p = Child.build('echo Hello; sleep 1', :timeout => 0.05)
|
110
|
-
assert_raises
|
111
|
-
|
112
|
-
|
186
|
+
p = Child.build('echo Hello; sleep 1', :timeout => 0.05, :pgroup_kill => true)
|
187
|
+
assert_raises(TimeoutExceeded) { p.exec! }
|
188
|
+
assert_process_reaped p.pid
|
189
|
+
assert_process_group_reaped Process.pid
|
113
190
|
assert (Time.now-start) <= 0.2
|
114
191
|
assert_equal "Hello\n", p.out
|
115
192
|
end
|
data/test/test_spawn.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: posix-spawn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Tomayko
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2020-07-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|
@@ -52,6 +52,7 @@ extra_rdoc_files:
|
|
52
52
|
- HACKING
|
53
53
|
files:
|
54
54
|
- ".gitignore"
|
55
|
+
- ".travis.yml"
|
55
56
|
- COPYING
|
56
57
|
- Gemfile
|
57
58
|
- HACKING
|
@@ -75,7 +76,6 @@ files:
|
|
75
76
|
homepage: https://github.com/rtomayko/posix-spawn
|
76
77
|
licenses:
|
77
78
|
- MIT
|
78
|
-
- LGPL
|
79
79
|
metadata: {}
|
80
80
|
post_install_message:
|
81
81
|
rdoc_options: []
|
@@ -92,8 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
94
|
requirements: []
|
95
|
-
|
96
|
-
rubygems_version: 2.2.2
|
95
|
+
rubygems_version: 3.0.3
|
97
96
|
signing_key:
|
98
97
|
specification_version: 4
|
99
98
|
summary: posix_spawnp(2) for ruby
|