open4 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.
- data/lib/open4.rb +19 -2
- data/open4.gemspec +2 -1
- data/test/popen4ext_test.rb +82 -0
- metadata +21 -42
data/lib/open4.rb
CHANGED
@@ -4,7 +4,7 @@ require 'timeout'
|
|
4
4
|
require 'thread'
|
5
5
|
|
6
6
|
module Open4
|
7
|
-
VERSION = '1.
|
7
|
+
VERSION = '1.3.0'
|
8
8
|
def self.version() VERSION end
|
9
9
|
|
10
10
|
class Error < ::StandardError; end
|
@@ -38,7 +38,17 @@ module Open4
|
|
38
38
|
module_function :popen4
|
39
39
|
module_function :open4
|
40
40
|
|
41
|
-
def
|
41
|
+
def popen4ext(closefds=false, *cmd, &b)
|
42
|
+
Open4.do_popen(b, :init, closefds) do |ps_read, ps_write|
|
43
|
+
ps_read.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
44
|
+
ps_write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
45
|
+
exec(*cmd)
|
46
|
+
raise 'forty-two' # Is this really needed?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
module_function :popen4ext
|
50
|
+
|
51
|
+
def self.do_popen(b = nil, exception_propagation_at = nil, closefds=false, &cmd)
|
42
52
|
pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
|
43
53
|
|
44
54
|
verbose = $VERBOSE
|
@@ -46,6 +56,13 @@ module Open4
|
|
46
56
|
$VERBOSE = nil
|
47
57
|
|
48
58
|
cid = fork {
|
59
|
+
if closefds
|
60
|
+
exlist = [0, 1, 2] | [pw,pr,pe,ps].map{|p| [p.first.fileno, p.last.fileno] }.flatten
|
61
|
+
ObjectSpace.each_object(IO){|io|
|
62
|
+
io.close if (not io.closed?) and (not exlist.include? io.fileno)
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
49
66
|
pw.last.close
|
50
67
|
STDIN.reopen pw.first
|
51
68
|
pw.first.close
|
data/open4.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "open4"
|
6
|
-
spec.version = "1.
|
6
|
+
spec.version = "1.3.0"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "open4"
|
9
9
|
spec.description = "description: open4 kicks the ass"
|
@@ -29,6 +29,7 @@ Gem::Specification::new do |spec|
|
|
29
29
|
"test",
|
30
30
|
"test/pfork4_test.rb",
|
31
31
|
"test/popen4_test.rb",
|
32
|
+
"test/popen4ext_test.rb",
|
32
33
|
"test/support",
|
33
34
|
"test/support/test_case.rb",
|
34
35
|
"white_box",
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'test_case'
|
2
|
+
|
3
|
+
module Open4
|
4
|
+
|
5
|
+
class POpen4Test < TestCase
|
6
|
+
UNKNOWN_CMD = 'asdfadsfjlkkk'
|
7
|
+
UNKNOWN_CMD_ERRORS = [Errno::ENOENT, Errno::EINVAL]
|
8
|
+
|
9
|
+
def test_unknown_command_propagates_exception
|
10
|
+
err = assert_raises(*UNKNOWN_CMD_ERRORS) { popen4ext true, UNKNOWN_CMD }
|
11
|
+
assert_match /#{UNKNOWN_CMD}/, err.to_s if on_mri?
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_exception_propagation_avoids_zombie_child_process
|
15
|
+
assert_raises(*UNKNOWN_CMD_ERRORS) { popen4ext true, UNKNOWN_CMD }
|
16
|
+
assert_empty Process.waitall
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_exit_failure
|
20
|
+
code = 43
|
21
|
+
cid, _ = popen4ext true, %{ruby -e "exit #{43}"}
|
22
|
+
assert_equal code, wait_status(cid)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_exit_success
|
26
|
+
cid, _ = popen4ext true, %{ruby -e "exit"}
|
27
|
+
assert_equal 0, wait_status(cid)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_passes_child_pid_to_block
|
31
|
+
cmd = %{ruby -e "STDOUT.print Process.pid"}
|
32
|
+
cid_in_block = nil
|
33
|
+
cid_in_fun = nil
|
34
|
+
status = popen4ext(true, cmd) do |cid, _, stdout, _|
|
35
|
+
cid_in_block = cid
|
36
|
+
cid_in_fun = stdout.read.to_i
|
37
|
+
end
|
38
|
+
assert_equal cid_in_fun, cid_in_block
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_io_pipes_without_block
|
42
|
+
via_msg = 'foo'
|
43
|
+
err_msg = 'bar'
|
44
|
+
cmd = <<-END
|
45
|
+
ruby -e "
|
46
|
+
STDOUT.write STDIN.read
|
47
|
+
STDERR.write '#{err_msg}'
|
48
|
+
"
|
49
|
+
END
|
50
|
+
cid, stdin, stdout, stderr = popen4ext true, cmd
|
51
|
+
stdin.write via_msg
|
52
|
+
stdin.close
|
53
|
+
out_actual = stdout.read
|
54
|
+
err_actual = stderr.read
|
55
|
+
assert_equal via_msg, out_actual
|
56
|
+
assert_equal err_msg, err_actual
|
57
|
+
assert_equal 0, wait_status(cid)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_io_pipes_with_block
|
61
|
+
via_msg = 'foo'
|
62
|
+
err_msg = 'bar'
|
63
|
+
out_actual, err_actual = nil
|
64
|
+
cmd = <<-END
|
65
|
+
ruby -e "
|
66
|
+
STDOUT.write STDIN.read
|
67
|
+
STDERR.write '#{err_msg}'
|
68
|
+
"
|
69
|
+
END
|
70
|
+
status = popen4ext(true, cmd) do |_, stdin, stdout, stderr|
|
71
|
+
stdin.write via_msg
|
72
|
+
stdin.close
|
73
|
+
out_actual = stdout.read
|
74
|
+
err_actual = stderr.read
|
75
|
+
end
|
76
|
+
assert_equal via_msg, out_actual
|
77
|
+
assert_equal err_msg, err_actual
|
78
|
+
assert_equal 0, status.exitstatus
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
metadata
CHANGED
@@ -1,32 +1,22 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: open4
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 2
|
9
|
-
- 0
|
10
|
-
version: 1.2.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Ara T. Howard
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2011-10-05 00:00:00 Z
|
12
|
+
date: 2011-11-19 00:00:00.000000000 Z
|
19
13
|
dependencies: []
|
20
|
-
|
21
|
-
description: "description: open4 kicks the ass"
|
14
|
+
description: ! 'description: open4 kicks the ass'
|
22
15
|
email: ara.t.howard@gmail.com
|
23
16
|
executables: []
|
24
|
-
|
25
17
|
extensions: []
|
26
|
-
|
27
18
|
extra_rdoc_files: []
|
28
|
-
|
29
|
-
files:
|
19
|
+
files:
|
30
20
|
- LICENSE
|
31
21
|
- README
|
32
22
|
- README.erb
|
@@ -44,42 +34,31 @@ files:
|
|
44
34
|
- samples/timeout.rb
|
45
35
|
- test/pfork4_test.rb
|
46
36
|
- test/popen4_test.rb
|
37
|
+
- test/popen4ext_test.rb
|
47
38
|
- test/support/test_case.rb
|
48
39
|
- white_box/leak.rb
|
49
40
|
homepage: https://github.com/ahoward/open4
|
50
41
|
licenses: []
|
51
|
-
|
52
|
-
metadata: {}
|
53
|
-
|
54
42
|
post_install_message:
|
55
43
|
rdoc_options: []
|
56
|
-
|
57
|
-
require_paths:
|
44
|
+
require_paths:
|
58
45
|
- lib
|
59
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
47
|
none: false
|
61
|
-
requirements:
|
62
|
-
- -
|
63
|
-
- !ruby/object:Gem::Version
|
64
|
-
|
65
|
-
|
66
|
-
- 0
|
67
|
-
version: "0"
|
68
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
53
|
none: false
|
70
|
-
requirements:
|
71
|
-
- -
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
|
74
|
-
segments:
|
75
|
-
- 0
|
76
|
-
version: "0"
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
77
58
|
requirements: []
|
78
|
-
|
79
59
|
rubyforge_project: codeforpeople
|
80
|
-
rubygems_version: 1.8.
|
60
|
+
rubygems_version: 1.8.11
|
81
61
|
signing_key:
|
82
|
-
specification_version:
|
62
|
+
specification_version: 3
|
83
63
|
summary: open4
|
84
64
|
test_files: []
|
85
|
-
|