childprocess 0.8.0 → 2.0.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.
Files changed (51) hide show
  1. checksums.yaml +5 -5
  2. data/.document +6 -6
  3. data/.gitignore +28 -28
  4. data/.rspec +1 -1
  5. data/.travis.yml +42 -36
  6. data/CHANGELOG.md +67 -44
  7. data/Gemfile +18 -15
  8. data/LICENSE +20 -20
  9. data/README.md +216 -192
  10. data/Rakefile +61 -61
  11. data/appveyor.yml +42 -43
  12. data/childprocess.gemspec +32 -30
  13. data/ext/mkrf_conf.rb +24 -0
  14. data/lib/childprocess/abstract_io.rb +36 -36
  15. data/lib/childprocess/abstract_process.rb +192 -192
  16. data/lib/childprocess/errors.rb +37 -26
  17. data/lib/childprocess/jruby/io.rb +16 -16
  18. data/lib/childprocess/jruby/process.rb +184 -159
  19. data/lib/childprocess/jruby/pump.rb +53 -53
  20. data/lib/childprocess/jruby.rb +56 -56
  21. data/lib/childprocess/tools/generator.rb +145 -145
  22. data/lib/childprocess/unix/fork_exec_process.rb +78 -70
  23. data/lib/childprocess/unix/io.rb +21 -21
  24. data/lib/childprocess/unix/lib.rb +186 -186
  25. data/lib/childprocess/unix/platform/i386-linux.rb +12 -12
  26. data/lib/childprocess/unix/platform/i386-solaris.rb +11 -11
  27. data/lib/childprocess/unix/platform/x86_64-linux.rb +12 -12
  28. data/lib/childprocess/unix/platform/x86_64-macosx.rb +11 -11
  29. data/lib/childprocess/unix/posix_spawn_process.rb +134 -134
  30. data/lib/childprocess/unix/process.rb +90 -89
  31. data/lib/childprocess/unix.rb +9 -9
  32. data/lib/childprocess/version.rb +3 -3
  33. data/lib/childprocess/windows/handle.rb +91 -91
  34. data/lib/childprocess/windows/io.rb +25 -25
  35. data/lib/childprocess/windows/lib.rb +416 -416
  36. data/lib/childprocess/windows/process.rb +130 -130
  37. data/lib/childprocess/windows/process_builder.rb +178 -175
  38. data/lib/childprocess/windows/structs.rb +148 -148
  39. data/lib/childprocess/windows.rb +33 -33
  40. data/lib/childprocess.rb +210 -205
  41. data/spec/abstract_io_spec.rb +12 -12
  42. data/spec/childprocess_spec.rb +447 -391
  43. data/spec/get_env.ps1 +13 -0
  44. data/spec/io_spec.rb +228 -228
  45. data/spec/jruby_spec.rb +24 -24
  46. data/spec/pid_behavior.rb +12 -12
  47. data/spec/platform_detection_spec.rb +86 -86
  48. data/spec/spec_helper.rb +270 -261
  49. data/spec/unix_spec.rb +57 -57
  50. data/spec/windows_spec.rb +23 -23
  51. metadata +18 -33
@@ -1,146 +1,146 @@
1
- require 'fileutils'
2
-
3
- module ChildProcess
4
- module Tools
5
- class Generator
6
- EXE_NAME = "childprocess-sizeof-generator"
7
- TMP_PROGRAM = "childprocess-sizeof-generator.c"
8
- DEFAULT_INCLUDES = %w[stdio.h stddef.h]
9
-
10
- def self.generate
11
- new.generate
12
- end
13
-
14
- def initialize
15
- @cc = ENV['CC'] || 'gcc'
16
- @out = File.expand_path("../../unix/platform/#{ChildProcess.platform_name}.rb", __FILE__)
17
- @sizeof = {}
18
- @constants = {}
19
- end
20
-
21
- def generate
22
- fetch_size 'posix_spawn_file_actions_t', :include => "spawn.h"
23
- fetch_size 'posix_spawnattr_t', :include => "spawn.h"
24
- fetch_size 'sigset_t', :include => "signal.h"
25
-
26
- fetch_constant 'POSIX_SPAWN_RESETIDS', :include => 'spawn.h'
27
- fetch_constant 'POSIX_SPAWN_SETPGROUP', :include => 'spawn.h'
28
- fetch_constant 'POSIX_SPAWN_SETSIGDEF', :include => 'spawn.h'
29
- fetch_constant 'POSIX_SPAWN_SETSIGMASK', :include => 'spawn.h'
30
-
31
- if ChildProcess.linux?
32
- fetch_constant 'POSIX_SPAWN_USEVFORK', :include => 'spawn.h', :define => {'_GNU_SOURCE' => nil}
33
- end
34
-
35
- write
36
- end
37
-
38
- def write
39
- FileUtils.mkdir_p(File.dirname(@out))
40
- File.open(@out, 'w') do |io|
41
- io.puts result
42
- end
43
-
44
- puts "wrote #{@out}"
45
- end
46
-
47
- def fetch_size(type_name, opts = {})
48
- print "sizeof(#{type_name}): "
49
- src = <<-EOF
50
- int main() {
51
- printf("%d", (unsigned int)sizeof(#{type_name}));
52
- return 0;
53
- }
54
- EOF
55
-
56
- output = execute(src, opts)
57
-
58
- if output.to_i < 1
59
- raise "sizeof(#{type_name}) == #{output.to_i} (output=#{output})"
60
- end
61
-
62
- size = output.to_i
63
- @sizeof[type_name] = size
64
-
65
- puts size
66
- end
67
-
68
- def fetch_constant(name, opts)
69
- print "#{name}: "
70
- src = <<-EOF
71
- int main() {
72
- printf("%d", (unsigned int)#{name});
73
- return 0;
74
- }
75
- EOF
76
-
77
- output = execute(src, opts)
78
- value = Integer(output)
79
- @constants[name] = value
80
-
81
- puts value
82
- end
83
-
84
-
85
- def execute(src, opts)
86
- program = Array(opts[:define]).map do |key, value|
87
- <<-SRC
88
- #ifndef #{key}
89
- #define #{key} #{value}
90
- #endif
91
- SRC
92
- end.join("\n")
93
- program << "\n"
94
-
95
- includes = Array(opts[:include]) + DEFAULT_INCLUDES
96
- program << includes.map { |include| "#include <#{include}>" }.join("\n")
97
- program << "\n#{src}"
98
-
99
- File.open(TMP_PROGRAM, 'w') do |file|
100
- file << program
101
- end
102
-
103
- cmd = "#{@cc} #{TMP_PROGRAM} -o #{EXE_NAME}"
104
- system cmd
105
- unless $?.success?
106
- raise "failed to compile program: #{cmd.inspect}\n#{program}"
107
- end
108
-
109
- output = `./#{EXE_NAME} 2>&1`
110
-
111
- unless $?.success?
112
- raise "failed to run program: #{cmd.inspect}\n#{output}"
113
- end
114
-
115
- output.chomp
116
- ensure
117
- File.delete TMP_PROGRAM if File.exist?(TMP_PROGRAM)
118
- File.delete EXE_NAME if File.exist?(EXE_NAME)
119
- end
120
-
121
- def result
122
- if @sizeof.empty? && @constants.empty?
123
- raise "no data collected, nothing to do"
124
- end
125
-
126
- out = ['module ChildProcess::Unix::Platform']
127
- out << ' SIZEOF = {'
128
-
129
- max = @sizeof.keys.map { |e| e.length }.max
130
- @sizeof.each_with_index do |(type, size), idx|
131
- out << " :#{type.ljust max} => #{size}#{',' unless idx == @sizeof.size - 1}"
132
- end
133
- out << ' }'
134
-
135
- max = @constants.keys.map { |e| e.length }.max
136
- @constants.each do |name, val|
137
- out << " #{name.ljust max} = #{val}"
138
- end
139
- out << 'end'
140
-
141
- out.join "\n"
142
- end
143
-
144
- end
145
- end
1
+ require 'fileutils'
2
+
3
+ module ChildProcess
4
+ module Tools
5
+ class Generator
6
+ EXE_NAME = "childprocess-sizeof-generator"
7
+ TMP_PROGRAM = "childprocess-sizeof-generator.c"
8
+ DEFAULT_INCLUDES = %w[stdio.h stddef.h]
9
+
10
+ def self.generate
11
+ new.generate
12
+ end
13
+
14
+ def initialize
15
+ @cc = ENV['CC'] || 'gcc'
16
+ @out = File.expand_path("../../unix/platform/#{ChildProcess.platform_name}.rb", __FILE__)
17
+ @sizeof = {}
18
+ @constants = {}
19
+ end
20
+
21
+ def generate
22
+ fetch_size 'posix_spawn_file_actions_t', :include => "spawn.h"
23
+ fetch_size 'posix_spawnattr_t', :include => "spawn.h"
24
+ fetch_size 'sigset_t', :include => "signal.h"
25
+
26
+ fetch_constant 'POSIX_SPAWN_RESETIDS', :include => 'spawn.h'
27
+ fetch_constant 'POSIX_SPAWN_SETPGROUP', :include => 'spawn.h'
28
+ fetch_constant 'POSIX_SPAWN_SETSIGDEF', :include => 'spawn.h'
29
+ fetch_constant 'POSIX_SPAWN_SETSIGMASK', :include => 'spawn.h'
30
+
31
+ if ChildProcess.linux?
32
+ fetch_constant 'POSIX_SPAWN_USEVFORK', :include => 'spawn.h', :define => {'_GNU_SOURCE' => nil}
33
+ end
34
+
35
+ write
36
+ end
37
+
38
+ def write
39
+ FileUtils.mkdir_p(File.dirname(@out))
40
+ File.open(@out, 'w') do |io|
41
+ io.puts result
42
+ end
43
+
44
+ puts "wrote #{@out}"
45
+ end
46
+
47
+ def fetch_size(type_name, opts = {})
48
+ print "sizeof(#{type_name}): "
49
+ src = <<-EOF
50
+ int main() {
51
+ printf("%d", (unsigned int)sizeof(#{type_name}));
52
+ return 0;
53
+ }
54
+ EOF
55
+
56
+ output = execute(src, opts)
57
+
58
+ if output.to_i < 1
59
+ raise "sizeof(#{type_name}) == #{output.to_i} (output=#{output})"
60
+ end
61
+
62
+ size = output.to_i
63
+ @sizeof[type_name] = size
64
+
65
+ puts size
66
+ end
67
+
68
+ def fetch_constant(name, opts)
69
+ print "#{name}: "
70
+ src = <<-EOF
71
+ int main() {
72
+ printf("%d", (unsigned int)#{name});
73
+ return 0;
74
+ }
75
+ EOF
76
+
77
+ output = execute(src, opts)
78
+ value = Integer(output)
79
+ @constants[name] = value
80
+
81
+ puts value
82
+ end
83
+
84
+
85
+ def execute(src, opts)
86
+ program = Array(opts[:define]).map do |key, value|
87
+ <<-SRC
88
+ #ifndef #{key}
89
+ #define #{key} #{value}
90
+ #endif
91
+ SRC
92
+ end.join("\n")
93
+ program << "\n"
94
+
95
+ includes = Array(opts[:include]) + DEFAULT_INCLUDES
96
+ program << includes.map { |include| "#include <#{include}>" }.join("\n")
97
+ program << "\n#{src}"
98
+
99
+ File.open(TMP_PROGRAM, 'w') do |file|
100
+ file << program
101
+ end
102
+
103
+ cmd = "#{@cc} #{TMP_PROGRAM} -o #{EXE_NAME}"
104
+ system cmd
105
+ unless $?.success?
106
+ raise "failed to compile program: #{cmd.inspect}\n#{program}"
107
+ end
108
+
109
+ output = `./#{EXE_NAME} 2>&1`
110
+
111
+ unless $?.success?
112
+ raise "failed to run program: #{cmd.inspect}\n#{output}"
113
+ end
114
+
115
+ output.chomp
116
+ ensure
117
+ File.delete TMP_PROGRAM if File.exist?(TMP_PROGRAM)
118
+ File.delete EXE_NAME if File.exist?(EXE_NAME)
119
+ end
120
+
121
+ def result
122
+ if @sizeof.empty? && @constants.empty?
123
+ raise "no data collected, nothing to do"
124
+ end
125
+
126
+ out = ['module ChildProcess::Unix::Platform']
127
+ out << ' SIZEOF = {'
128
+
129
+ max = @sizeof.keys.map { |e| e.length }.max
130
+ @sizeof.each_with_index do |(type, size), idx|
131
+ out << " :#{type.ljust max} => #{size}#{',' unless idx == @sizeof.size - 1}"
132
+ end
133
+ out << ' }'
134
+
135
+ max = @constants.keys.map { |e| e.length }.max
136
+ @constants.each do |name, val|
137
+ out << " #{name.ljust max} = #{val}"
138
+ end
139
+ out << 'end'
140
+
141
+ out.join "\n"
142
+ end
143
+
144
+ end
145
+ end
146
146
  end
@@ -1,70 +1,78 @@
1
- module ChildProcess
2
- module Unix
3
- class ForkExecProcess < Process
4
- private
5
-
6
- def launch_process
7
- if @io
8
- stdout = @io.stdout
9
- stderr = @io.stderr
10
- end
11
-
12
- # pipe used to detect exec() failure
13
- exec_r, exec_w = ::IO.pipe
14
- ChildProcess.close_on_exec exec_w
15
-
16
- if duplex?
17
- reader, writer = ::IO.pipe
18
- end
19
-
20
- @pid = Kernel.fork {
21
- # Children of the forked process will inherit its process group
22
- # This is to make sure that all grandchildren dies when this Process instance is killed
23
- ::Process.setpgid 0, 0 if leader?
24
-
25
- if @cwd
26
- Dir.chdir(@cwd)
27
- end
28
-
29
- exec_r.close
30
- set_env
31
-
32
- STDOUT.reopen(stdout || "/dev/null")
33
- STDERR.reopen(stderr || "/dev/null")
34
-
35
- if duplex?
36
- STDIN.reopen(reader)
37
- writer.close
38
- end
39
-
40
- executable, *args = @args
41
-
42
- begin
43
- Kernel.exec([executable, executable], *args)
44
- rescue SystemCallError => ex
45
- exec_w << ex.message
46
- end
47
- }
48
-
49
- exec_w.close
50
-
51
- if duplex?
52
- io._stdin = writer
53
- reader.close
54
- end
55
-
56
- # if we don't eventually get EOF, exec() failed
57
- unless exec_r.eof?
58
- raise LaunchError, exec_r.read || "executing command with #{@args.inspect} failed"
59
- end
60
-
61
- ::Process.detach(@pid) if detach?
62
- end
63
-
64
- def set_env
65
- @environment.each { |k, v| ENV[k.to_s] = v.nil? ? nil : v.to_s }
66
- end
67
-
68
- end # Process
69
- end # Unix
70
- end # ChildProcess
1
+ module ChildProcess
2
+ module Unix
3
+ class ForkExecProcess < Process
4
+ private
5
+
6
+ def launch_process
7
+ if @io
8
+ stdout = @io.stdout
9
+ stderr = @io.stderr
10
+ end
11
+
12
+ # pipe used to detect exec() failure
13
+ exec_r, exec_w = ::IO.pipe
14
+ ChildProcess.close_on_exec exec_w
15
+
16
+ if duplex?
17
+ reader, writer = ::IO.pipe
18
+ end
19
+
20
+ @pid = Kernel.fork {
21
+ # Children of the forked process will inherit its process group
22
+ # This is to make sure that all grandchildren dies when this Process instance is killed
23
+ ::Process.setpgid 0, 0 if leader?
24
+
25
+ if @cwd
26
+ Dir.chdir(@cwd)
27
+ end
28
+
29
+ exec_r.close
30
+ set_env
31
+
32
+ if stdout
33
+ STDOUT.reopen(stdout)
34
+ else
35
+ STDOUT.reopen("/dev/null", "a+")
36
+ end
37
+ if stderr
38
+ STDERR.reopen(stderr)
39
+ else
40
+ STDERR.reopen("/dev/null", "a+")
41
+ end
42
+
43
+ if duplex?
44
+ STDIN.reopen(reader)
45
+ writer.close
46
+ end
47
+
48
+ executable, *args = @args
49
+
50
+ begin
51
+ Kernel.exec([executable, executable], *args)
52
+ rescue SystemCallError => ex
53
+ exec_w << ex.message
54
+ end
55
+ }
56
+
57
+ exec_w.close
58
+
59
+ if duplex?
60
+ io._stdin = writer
61
+ reader.close
62
+ end
63
+
64
+ # if we don't eventually get EOF, exec() failed
65
+ unless exec_r.eof?
66
+ raise LaunchError, exec_r.read || "executing command with #{@args.inspect} failed"
67
+ end
68
+
69
+ ::Process.detach(@pid) if detach?
70
+ end
71
+
72
+ def set_env
73
+ @environment.each { |k, v| ENV[k.to_s] = v.nil? ? nil : v.to_s }
74
+ end
75
+
76
+ end # Process
77
+ end # Unix
78
+ end # ChildProcess
@@ -1,21 +1,21 @@
1
- module ChildProcess
2
- module Unix
3
- class IO < AbstractIO
4
- private
5
-
6
- def check_type(io)
7
- unless io.respond_to? :to_io
8
- raise ArgumentError, "expected #{io.inspect} to respond to :to_io"
9
- end
10
-
11
- result = io.to_io
12
- unless result && result.kind_of?(::IO)
13
- raise TypeError, "expected IO, got #{result.inspect}:#{result.class}"
14
- end
15
- end
16
-
17
- end # IO
18
- end # Unix
19
- end # ChildProcess
20
-
21
-
1
+ module ChildProcess
2
+ module Unix
3
+ class IO < AbstractIO
4
+ private
5
+
6
+ def check_type(io)
7
+ unless io.respond_to? :to_io
8
+ raise ArgumentError, "expected #{io.inspect} to respond to :to_io"
9
+ end
10
+
11
+ result = io.to_io
12
+ unless result && result.kind_of?(::IO)
13
+ raise TypeError, "expected IO, got #{result.inspect}:#{result.class}"
14
+ end
15
+ end
16
+
17
+ end # IO
18
+ end # Unix
19
+ end # ChildProcess
20
+
21
+