childprocess 0.8.0 → 3.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 (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 +40 -36
  6. data/CHANGELOG.md +73 -44
  7. data/Gemfile +21 -15
  8. data/LICENSE +20 -20
  9. data/README.md +218 -192
  10. data/Rakefile +61 -61
  11. data/appveyor.yml +42 -43
  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 +130 -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 -391
  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