/usr/lib/ruby/vendor_ruby/childprocess/windows/lib.rb is in ruby-childprocess 0.5.9-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 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 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 | module ChildProcess
module Windows
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000
PROCESS_ALL_ACCESS = 0x1F0FFF
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_READ = 0x0010
PROCESS_STILL_ACTIVE = 259
INFINITE = 0xFFFFFFFF
WIN_SIGINT = 2
WIN_SIGBREAK = 3
WIN_SIGKILL = 9
CTRL_C_EVENT = 0
CTRL_BREAK_EVENT = 1
CREATE_BREAKAWAY_FROM_JOB = 0x01000000
DETACHED_PROCESS = 0x00000008
STARTF_USESTDHANDLES = 0x00000100
INVALID_HANDLE_VALUE = -1
HANDLE_FLAG_INHERIT = 0x00000001
DUPLICATE_SAME_ACCESS = 0x00000002
CREATE_UNICODE_ENVIRONMENT = 0x00000400
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000
JOB_OBJECT_EXTENDED_LIMIT_INFORMATION = 9
JOB_OBJECT_BASIC_LIMIT_INFORMATION = 2
module Lib
enum :wait_status, [
:wait_object_0, 0,
:wait_timeout, 0x102,
:wait_abandoned, 0x80,
:wait_failed, 0xFFFFFFFF
]
#
# BOOL WINAPI CreateProcess(
# __in_opt LPCTSTR lpApplicationName,
# __inout_opt LPTSTR lpCommandLine,
# __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
# __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
# __in BOOL bInheritHandles,
# __in DWORD dwCreationFlags,
# __in_opt LPVOID lpEnvironment,
# __in_opt LPCTSTR lpCurrentDirectory,
# __in LPSTARTUPINFO lpStartupInfo,
# __out LPPROCESS_INFORMATION lpProcessInformation
# );
#
attach_function :create_process, :CreateProcessA, [
:pointer,
:pointer,
:pointer,
:pointer,
:bool,
:ulong,
:pointer,
:pointer,
:pointer,
:pointer], :bool
#
# DWORD WINAPI FormatMessage(
# __in DWORD dwFlags,
# __in_opt LPCVOID lpSource,
# __in DWORD dwMessageId,
# __in DWORD dwLanguageId,
# __out LPTSTR lpBuffer,
# __in DWORD nSize,
# __in_opt va_list *Arguments
# );
#
attach_function :format_message, :FormatMessageA, [
:ulong,
:pointer,
:ulong,
:ulong,
:pointer,
:ulong,
:pointer], :ulong
attach_function :close_handle, :CloseHandle, [:pointer], :bool
#
# HANDLE WINAPI OpenProcess(
# __in DWORD dwDesiredAccess,
# __in BOOL bInheritHandle,
# __in DWORD dwProcessId
# );
#
attach_function :open_process, :OpenProcess, [:ulong, :bool, :ulong], :pointer
#
# HANDLE WINAPI CreateJobObject(
# _In_opt_ LPSECURITY_ATTRIBUTES lpJobAttributes,
# _In_opt_ LPCTSTR lpName
# );
#
attach_function :create_job_object, :CreateJobObjectA, [:pointer, :pointer], :pointer
#
# BOOL WINAPI AssignProcessToJobObject(
# _In_ HANDLE hJob,
# _In_ HANDLE hProcess
# );
attach_function :assign_process_to_job_object, :AssignProcessToJobObject, [:pointer, :pointer], :bool
#
# BOOL WINAPI SetInformationJobObject(
# _In_ HANDLE hJob,
# _In_ JOBOBJECTINFOCLASS JobObjectInfoClass,
# _In_ LPVOID lpJobObjectInfo,
# _In_ DWORD cbJobObjectInfoLength
# );
#
attach_function :set_information_job_object, :SetInformationJobObject, [:pointer, :int, :pointer, :ulong], :bool
#
#
# DWORD WINAPI WaitForSingleObject(
# __in HANDLE hHandle,
# __in DWORD dwMilliseconds
# );
#
attach_function :wait_for_single_object, :WaitForSingleObject, [:pointer, :ulong], :wait_status, :blocking => true
#
# BOOL WINAPI GetExitCodeProcess(
# __in HANDLE hProcess,
# __out LPDWORD lpExitCode
# );
#
attach_function :get_exit_code, :GetExitCodeProcess, [:pointer, :pointer], :bool
#
# BOOL WINAPI GenerateConsoleCtrlEvent(
# __in DWORD dwCtrlEvent,
# __in DWORD dwProcessGroupId
# );
#
attach_function :generate_console_ctrl_event, :GenerateConsoleCtrlEvent, [:ulong, :ulong], :bool
#
# BOOL WINAPI TerminateProcess(
# __in HANDLE hProcess,
# __in UINT uExitCode
# );
#
attach_function :terminate_process, :TerminateProcess, [:pointer, :uint], :bool
#
# intptr_t _get_osfhandle(
# int fd
# );
#
attach_function :get_osfhandle, :_get_osfhandle, [:int], :intptr_t
#
# int _open_osfhandle (
# intptr_t osfhandle,
# int flags
# );
#
attach_function :open_osfhandle, :_open_osfhandle, [:pointer, :int], :int
# BOOL WINAPI SetHandleInformation(
# __in HANDLE hObject,
# __in DWORD dwMask,
# __in DWORD dwFlags
# );
attach_function :set_handle_information, :SetHandleInformation, [:pointer, :ulong, :ulong], :bool
# BOOL WINAPI GetHandleInformation(
# __in HANDLE hObject,
# __out LPDWORD lpdwFlags
# );
attach_function :get_handle_information, :GetHandleInformation, [:pointer, :pointer], :bool
# BOOL WINAPI CreatePipe(
# __out PHANDLE hReadPipe,
# __out PHANDLE hWritePipe,
# __in_opt LPSECURITY_ATTRIBUTES lpPipeAttributes,
# __in DWORD nSize
# );
attach_function :create_pipe, :CreatePipe, [:pointer, :pointer, :pointer, :ulong], :bool
#
# HANDLE WINAPI GetCurrentProcess(void);
#
attach_function :current_process, :GetCurrentProcess, [], :pointer
#
# BOOL WINAPI DuplicateHandle(
# __in HANDLE hSourceProcessHandle,
# __in HANDLE hSourceHandle,
# __in HANDLE hTargetProcessHandle,
# __out LPHANDLE lpTargetHandle,
# __in DWORD dwDesiredAccess,
# __in BOOL bInheritHandle,
# __in DWORD dwOptions
# );
#
attach_function :_duplicate_handle, :DuplicateHandle, [
:pointer,
:pointer,
:pointer,
:pointer,
:ulong,
:bool,
:ulong
], :bool
class << self
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
# Do nothing
else
raise Error, "invalid signal #{signal.inspect}"
end
pids.map { |pid| pid if Lib.send_signal(signal, pid) }.compact
end
def waitpid(pid, flags = 0)
wait_for_pid(pid, no_hang?(flags))
end
def waitpid2(pid, flags = 0)
code = wait_for_pid(pid, no_hang?(flags))
[pid, code] if code
end
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
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
def each_child_of(pid, &blk)
raise NotImplementedError
# http://stackoverflow.com/questions/1173342/terminate-a-process-tree-c-for-windows?rq=1
# for each process entry
# if pe.th32ParentProcessID == pid
# Handle.open(pe.pe.th32ProcessId, &blk)
# end
#
end
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
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
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
def set_handle_inheritance(handle, bool)
status = set_handle_information(
handle,
HANDLE_FLAG_INHERIT,
bool ? HANDLE_FLAG_INHERIT : 0
)
check_error status
end
def get_handle_inheritance(handle)
flags = FFI::MemoryPointer.new(:uint)
status = get_handle_information(
handle,
flags
)
check_error status
flags.read_uint
end
def check_error(bool)
bool or raise Error, last_error_message
end
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
def no_hang?(flags)
(flags & Process::WNOHANG) == Process::WNOHANG
end
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
end
end # Lib
end # Windows
end # ChildProcess
|