childprocess 0.9.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) 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 +37 -44
  6. data/CHANGELOG.md +77 -49
  7. data/Gemfile +21 -15
  8. data/LICENSE +20 -20
  9. data/README.md +230 -196
  10. data/Rakefile +61 -61
  11. data/appveyor.yml +36 -60
  12. data/childprocess.gemspec +26 -30
  13. data/lib/childprocess.rb +210 -205
  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.rb +56 -56
  18. data/lib/childprocess/jruby/io.rb +16 -16
  19. data/lib/childprocess/jruby/process.rb +184 -159
  20. data/lib/childprocess/jruby/pump.rb +53 -53
  21. data/lib/childprocess/tools/generator.rb +145 -145
  22. data/lib/childprocess/unix.rb +9 -9
  23. data/lib/childprocess/unix/fork_exec_process.rb +78 -70
  24. data/lib/childprocess/unix/io.rb +21 -21
  25. data/lib/childprocess/unix/lib.rb +186 -186
  26. data/lib/childprocess/unix/platform/i386-linux.rb +12 -12
  27. data/lib/childprocess/unix/platform/i386-solaris.rb +11 -11
  28. data/lib/childprocess/unix/platform/x86_64-linux.rb +12 -12
  29. data/lib/childprocess/unix/platform/x86_64-macosx.rb +11 -11
  30. data/lib/childprocess/unix/posix_spawn_process.rb +134 -134
  31. data/lib/childprocess/unix/process.rb +90 -89
  32. data/lib/childprocess/version.rb +3 -3
  33. data/lib/childprocess/windows.rb +38 -33
  34. data/lib/childprocess/windows/handle.rb +91 -91
  35. data/lib/childprocess/windows/io.rb +25 -25
  36. data/lib/childprocess/windows/lib.rb +416 -416
  37. data/lib/childprocess/windows/process.rb +131 -130
  38. data/lib/childprocess/windows/process_builder.rb +178 -175
  39. data/lib/childprocess/windows/structs.rb +148 -148
  40. data/spec/abstract_io_spec.rb +12 -12
  41. data/spec/childprocess_spec.rb +447 -422
  42. data/spec/get_env.ps1 +13 -0
  43. data/spec/io_spec.rb +228 -228
  44. data/spec/jruby_spec.rb +24 -24
  45. data/spec/pid_behavior.rb +12 -12
  46. data/spec/platform_detection_spec.rb +86 -86
  47. data/spec/spec_helper.rb +270 -261
  48. data/spec/unix_spec.rb +57 -57
  49. data/spec/windows_spec.rb +23 -23
  50. metadata +8 -39
@@ -1,53 +1,53 @@
1
- module ChildProcess
2
- module JRuby
3
- class Pump
4
- BUFFER_SIZE = 2048
5
-
6
- def initialize(input, output)
7
- @input = input
8
- @output = output
9
- @stop = false
10
- end
11
-
12
- def stop
13
- @stop = true
14
- @thread && @thread.join
15
- end
16
-
17
- def run
18
- @thread = Thread.new { pump }
19
-
20
- self
21
- end
22
-
23
- private
24
-
25
- def pump
26
- buffer = Java.byte[BUFFER_SIZE].new
27
-
28
- until @stop && (@input.available == 0)
29
- read, avail = 0, 0
30
-
31
- while read != -1
32
- avail = [@input.available, 1].max
33
- avail = BUFFER_SIZE if avail > BUFFER_SIZE
34
- read = @input.read(buffer, 0, avail)
35
-
36
- if read > 0
37
- @output.write(buffer, 0, read)
38
- @output.flush
39
- end
40
- end
41
-
42
- sleep 0.1
43
- end
44
-
45
- @output.flush
46
- rescue java.io.IOException => ex
47
- ChildProcess.logger.debug ex.message
48
- ChildProcess.logger.debug ex.backtrace
49
- end
50
-
51
- end # Pump
52
- end # JRuby
53
- end # ChildProcess
1
+ module ChildProcess
2
+ module JRuby
3
+ class Pump
4
+ BUFFER_SIZE = 2048
5
+
6
+ def initialize(input, output)
7
+ @input = input
8
+ @output = output
9
+ @stop = false
10
+ end
11
+
12
+ def stop
13
+ @stop = true
14
+ @thread && @thread.join
15
+ end
16
+
17
+ def run
18
+ @thread = Thread.new { pump }
19
+
20
+ self
21
+ end
22
+
23
+ private
24
+
25
+ def pump
26
+ buffer = Java.byte[BUFFER_SIZE].new
27
+
28
+ until @stop && (@input.available == 0)
29
+ read, avail = 0, 0
30
+
31
+ while read != -1
32
+ avail = [@input.available, 1].max
33
+ avail = BUFFER_SIZE if avail > BUFFER_SIZE
34
+ read = @input.read(buffer, 0, avail)
35
+
36
+ if read > 0
37
+ @output.write(buffer, 0, read)
38
+ @output.flush
39
+ end
40
+ end
41
+
42
+ sleep 0.1
43
+ end
44
+
45
+ @output.flush
46
+ rescue java.io.IOException => ex
47
+ ChildProcess.logger.debug ex.message
48
+ ChildProcess.logger.debug ex.backtrace
49
+ end
50
+
51
+ end # Pump
52
+ end # JRuby
53
+ end # ChildProcess
@@ -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,9 +1,9 @@
1
- module ChildProcess
2
- module Unix
3
- end
4
- end
5
-
6
- require "childprocess/unix/io"
7
- require "childprocess/unix/process"
8
- require "childprocess/unix/fork_exec_process"
9
- # PosixSpawnProcess + ffi is required on demand.
1
+ module ChildProcess
2
+ module Unix
3
+ end
4
+ end
5
+
6
+ require "childprocess/unix/io"
7
+ require "childprocess/unix/process"
8
+ require "childprocess/unix/fork_exec_process"
9
+ # PosixSpawnProcess + ffi is required on demand.
@@ -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