Class: Win32Open4::ProcessHandler
- Includes:
- Kernel32
- Defined in:
- lib/procreate/win32/open4.rb
Overview
Responsible for launching a process, forwarding its stdout & stderr, and catching its error code. TODO: stdin is not currently handled in the ProcessHandler#relay method, though it should be fairly straightforward to add.
Constant Summary
Constants included from Kernel32
Kernel32::API, Kernel32::ERROR_SUCCESS, Kernel32::FORMAT_MESSAGE_ARGUMENT_ARRAY, Kernel32::FORMAT_MESSAGE_FROM_SYSTEM, Kernel32::HANDLE_FLAG_INHERIT, Kernel32::HANDLE_FLAG_PROTECT_FROM_CLOSE, Kernel32::NORMAL_PRIORITY_CLASS, Kernel32::PROCESS_INFO_SIZE, Kernel32::SECURITY_ATTRIBUTES_SIZE, Kernel32::STARTF_USESHOWWINDOW, Kernel32::STARTF_USESTDHANDLES, Kernel32::STARTUP_INFO_SIZE, Kernel32::WAIT_ABANDONED, Kernel32::WAIT_ABANDONED_0, Kernel32::WAIT_FAILED, Kernel32::WAIT_OBJECT_0, Kernel32::WAIT_TIMEOUT
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(cmdline, params = {}) ⇒ ProcessHandler
constructor
A new instance of ProcessHandler.
- #relay ⇒ Object
- #run ⇒ Object
Methods included from Kernel32
close_handle, create_pipe, create_process, peek_named_pipe, raise_last_error!, read_file, set_handle_information, write_file
Constructor Details
#initialize(cmdline, params = {}) ⇒ ProcessHandler
Returns a new instance of ProcessHandler.
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/procreate/win32/open4.rb', line 203 def initialize cmdline, params={} stdin, @stdout, @stderr = params.values_at :stdin, :stdout, :stderr if stdin raise NotImplementError, 'no stdin forwarding yet' end # create 3 pipes pw, pr, pe = Array.new(3) { create_pipe } set_handle_information pw.last, HANDLE_FLAG_INHERIT, 0 set_handle_information pr.first, HANDLE_FLAG_INHERIT, 0 set_handle_information pe.first, HANDLE_FLAG_INHERIT, 0 @phandle, hThread, @processId, dwThreadId = create_process cmdline.to_s, pw.first, pr.last, pe.last # we have to close the handles, so the pipes terminate with the process close_handle pw.first close_handle pr.last close_handle pe.last finalizer = self.class.finalizer [@phandle, pw.last, pr.first, pe.first] ObjectSpace.define_finalizer self, finalizer @pr, @pe = pr, pe end |
Class Method Details
.finalizer(handles) ⇒ Object
229 230 231 232 233 |
# File 'lib/procreate/win32/open4.rb', line 229 def self.finalizer handles proc do handles.each { |h| close_handle h } end end |
Instance Method Details
#relay ⇒ Object
257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/procreate/win32/open4.rb', line 257 def relay stdout = '' avail = peek_named_pipe(@pr.first) stdout = read_file(@pr.first, avail) if avail > 0 stderr = '' avail = peek_named_pipe(@pe.first) stderr = read_file(@pe.first, avail) if avail > 0 @stdout << stdout if !stdout.empty? and @stdout @stderr << stderr if !stderr.empty? and @stderr end |
#run ⇒ Object
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/procreate/win32/open4.rb', line 235 def run loop do relay case WaitForSingleObject @phandle, 10 when WAIT_TIMEOUT # ok... when WAIT_OBJECT_0 relay exit_code = [0].pack 'L' if GetExitCodeProcess @phandle, exit_code exit_status = exit_code.unpack('L')[0] end return exit_status when -1, WAIT_ABANDONED, WAIT_FAILED raise_last_error! end sleep 0.01 end end |