alive?(pid)
click to toggle source
def alive?(pid)
handle = Lib.open_process(PROCESS_ALL_ACCESS, false, pid)
if handle.null?
false
else
ptr = FFI::MemoryPointer.new :ulong
Lib.check_error Lib.get_exit_code(handle, ptr)
ptr.read_ulong == PROCESS_STILL_ACTIVE
end
end
check_error(bool)
click to toggle source
def check_error(bool)
bool or raise Error, last_error_message
end
dont_inherit(file)
click to toggle source
def dont_inherit(file)
unless file.respond_to?(:fileno)
raise ArgumentError, "expected #{file.inspect} to respond to :fileno"
end
set_handle_inheritance(handle_for(file.fileno), false)
end
duplicate_handle(handle)
click to toggle source
def duplicate_handle(handle)
dup = FFI::MemoryPointer.new(:pointer)
proc = current_process
ok = Lib._duplicate_handle(
proc,
handle,
proc,
dup,
0,
false,
DUPLICATE_SAME_ACCESS
)
check_error ok
dup.read_pointer
ensure
close_handle proc
end
each_child_of(pid, &blk)
click to toggle source
def each_child_of(pid, &blk)
raise NotImplementedError
end
get_handle_inheritance(handle)
click to toggle source
def get_handle_inheritance(handle)
flags = FFI::MemoryPointer.new(:uint)
status = get_handle_information(
handle,
flags
)
check_error status
flags.read_uint
end
handle_for(fd_or_io)
click to toggle source
def handle_for(fd_or_io)
if fd_or_io.kind_of?(IO) || fd_or_io.respond_to?(:fileno)
if ChildProcess.jruby?
handle = ChildProcess::JRuby.windows_handle_for(fd_or_io)
else
handle = get_osfhandle(fd_or_io.fileno)
end
elsif fd_or_io.kind_of?(Fixnum)
handle = get_osfhandle(fd_or_io)
elsif fd_or_io.respond_to?(:to_io)
io = fd_or_io.to_io
unless io.kind_of?(IO)
raise TypeError, "expected #to_io to return an instance of IO"
end
handle = get_osfhandle(io.fileno)
else
raise TypeError, "invalid type: #{fd_or_io.inspect}"
end
if handle == INVALID_HANDLE_VALUE
raise Error, last_error_message
end
FFI::Pointer.new handle
end
io_for(handle, flags = File::RDONLY)
click to toggle source
def io_for(handle, flags = File::RDONLY)
fd = open_osfhandle(handle, flags)
if fd == -1
raise Error, last_error_message
end
FFI::IO.for_fd fd, flags
end
kill(signal, *pids)
click to toggle source
def kill(signal, *pids)
case signal
when 'SIGINT', 'INT', :SIGINT, :INT
signal = WIN_SIGINT
when 'SIGBRK', 'BRK', :SIGBREAK, :BRK
signal = WIN_SIGBREAK
when 'SIGKILL', 'KILL', :SIGKILL, :KILL
signal = WIN_SIGKILL
when 0..9
else
raise Error, "invalid signal #{signal.inspect}"
end
pids.map { |pid| pid if Lib.send_signal(signal, pid) }.compact
end
last_error_message()
click to toggle source
def last_error_message
errnum = FFI.errno
buf = FFI::MemoryPointer.new :char, 512
size = format_message(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
nil, errnum, 0, buf, buf.size, nil
)
str = buf.read_string(size).strip
if errnum == 0
"Unknown error (Windows says #{str.inspect}, but it did not.)"
else
"#{str} (#{errnum})"
end
end
msvcrt_name()
click to toggle source
def self.msvcrt_name
host_part = RbConfig::CONFIG['host_os'].split("_")[1]
manifest = File.join(RbConfig::CONFIG['bindir'], 'ruby.exe.manifest')
if host_part && host_part.to_i > 80 && File.exists?(manifest)
"msvcr#{host_part}"
else
"msvcrt"
end
end
no_hang?(flags)
click to toggle source
def no_hang?(flags)
(flags & Process::WNOHANG) == Process::WNOHANG
end
set_handle_inheritance(handle, bool)
click to toggle source
def set_handle_inheritance(handle, bool)
status = set_handle_information(
handle,
HANDLE_FLAG_INHERIT,
bool ? HANDLE_FLAG_INHERIT : 0
)
check_error status
end
wait_for_pid(pid, no_hang)
click to toggle source
def wait_for_pid(pid, no_hang)
code = Handle.open(pid) { |handle|
handle.wait unless no_hang
handle.exit_code
}
code if code != PROCESS_STILL_ACTIVE
end
waitpid(pid, flags = 0)
click to toggle source
def waitpid(pid, flags = 0)
wait_for_pid(pid, no_hang?(flags))
end
waitpid2(pid, flags = 0)
click to toggle source
def waitpid2(pid, flags = 0)
code = wait_for_pid(pid, no_hang?(flags))
[pid, code] if code
end