mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Should be the source code, not the binary!. Forgot Booleans!
git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@623 19e92222-5c0b-0410-8929-a290d50e31e9
This commit is contained in:
parent
e4d323e7b5
commit
e63cf0903b
3 changed files with 407 additions and 0 deletions
18
projects/mongrel_service/native/boolean.bi
Normal file
18
projects/mongrel_service/native/boolean.bi
Normal file
|
@ -0,0 +1,18 @@
|
|||
'#--
|
||||
'# Copyright (c) 2006-2007 Luis Lavena, Multimedia systems
|
||||
'#
|
||||
'# This source code is released under the MIT License.
|
||||
'# See MIT-LICENSE file for details
|
||||
'#++
|
||||
|
||||
#ifndef __BOOLEAN_BI__
|
||||
#define __BOOLEAN_BI__
|
||||
|
||||
#undef BOOLEAN
|
||||
type BOOLEAN as byte
|
||||
#undef FALSE
|
||||
const FALSE as byte = 0
|
||||
#undef TRUE
|
||||
const TRUE as byte = not FALSE
|
||||
|
||||
#endif ' __BOOLEAN_BI__
|
389
projects/mongrel_service/native/console_process.bas
Normal file
389
projects/mongrel_service/native/console_process.bas
Normal file
|
@ -0,0 +1,389 @@
|
|||
'#--
|
||||
'# Copyright (c) 2007 Luis Lavena, Multimedia systems
|
||||
'#
|
||||
'# This source code is released under the MIT License.
|
||||
'# See MIT-LICENSE file for details
|
||||
'#++
|
||||
|
||||
#include once "console_process.bi"
|
||||
|
||||
constructor ConsoleProcess(byref new_filename as string = "", byref new_arguments as string = "")
|
||||
'# assign filename and arguments
|
||||
|
||||
'# if filename contains spaces, automatically quote it!
|
||||
if (instr(new_filename, " ") > 0) then
|
||||
_filename = !"\"" + new_filename + !"\""
|
||||
else
|
||||
_filename = new_filename
|
||||
endif
|
||||
|
||||
_arguments = new_arguments
|
||||
end constructor
|
||||
|
||||
destructor ConsoleProcess()
|
||||
'# in case process still running
|
||||
if (running = true) then
|
||||
terminate(true)
|
||||
|
||||
'# close opened handles
|
||||
'# ...
|
||||
CloseHandle(_process_info.hProcess)
|
||||
CloseHandle(_process_info.hThread)
|
||||
end if
|
||||
end destructor
|
||||
|
||||
property ConsoleProcess.filename() as string
|
||||
return _filename
|
||||
end property
|
||||
|
||||
property ConsoleProcess.filename(byref rhs as string)
|
||||
if not (running = true) then
|
||||
_filename = rhs
|
||||
end if
|
||||
end property
|
||||
|
||||
property ConsoleProcess.arguments() as string
|
||||
return _arguments
|
||||
end property
|
||||
|
||||
property ConsoleProcess.arguments(byref rhs as string)
|
||||
if not (running = true) then
|
||||
_arguments = rhs
|
||||
end if
|
||||
end property
|
||||
|
||||
property ConsoleProcess.redirected_stdout() as string
|
||||
return _stdout_filename
|
||||
end property
|
||||
|
||||
property ConsoleProcess.redirected_stderr() as string
|
||||
return _stderr_filename
|
||||
end property
|
||||
|
||||
'# running is a helper which evaluates _pid and exit_code
|
||||
property ConsoleProcess.running() as boolean
|
||||
dim result as boolean
|
||||
|
||||
'# presume not running
|
||||
result = false
|
||||
|
||||
if not (_pid = 0) then
|
||||
'# that means the process is/was running.
|
||||
'# now evaluate if exit_code = STILL_ACTIVE
|
||||
result = (exit_code = STILL_ACTIVE)
|
||||
end if
|
||||
|
||||
return result
|
||||
end property
|
||||
|
||||
property ConsoleProcess.pid() as uinteger
|
||||
return _pid
|
||||
end property
|
||||
|
||||
property ConsoleProcess.exit_code() as uinteger
|
||||
dim result as uinteger
|
||||
|
||||
result = 0
|
||||
|
||||
'# is _pid valid?
|
||||
if not (_pid = 0) then
|
||||
if not (_process_info.hProcess = NULL) then
|
||||
'# the process reference is valid, get the exit_code
|
||||
if not (GetExitCodeProcess(_process_info.hProcess, @result) = 0) then
|
||||
'# OK
|
||||
'# no error in the query, get result
|
||||
end if '# not (GetExitCodeProcess() = 0)
|
||||
end if '# not (proc = NULL)
|
||||
end if '# not (_pid = 0)
|
||||
|
||||
return result
|
||||
end property
|
||||
|
||||
function ConsoleProcess.redirect(byval target as ProcessStdEnum, byref new_std_filename as string) as boolean
|
||||
dim result as boolean
|
||||
|
||||
if not (running = true) then
|
||||
select case target
|
||||
case ProcessStdOut:
|
||||
_stdout_filename = new_std_filename
|
||||
result = true
|
||||
|
||||
case ProcessStdErr:
|
||||
_stderr_filename = new_std_filename
|
||||
result = true
|
||||
|
||||
case ProcessStdBoth:
|
||||
_stdout_filename = new_std_filename
|
||||
_stderr_filename = new_std_filename
|
||||
result = true
|
||||
|
||||
end select
|
||||
end if
|
||||
|
||||
return result
|
||||
end function
|
||||
|
||||
function ConsoleProcess.start() as boolean
|
||||
dim result as boolean
|
||||
dim success as boolean
|
||||
|
||||
'# API
|
||||
'# New Process resources
|
||||
dim context as STARTUPINFO
|
||||
dim proc_sa as SECURITY_ATTRIBUTES = type(sizeof(SECURITY_ATTRIBUTES), NULL, TRUE)
|
||||
|
||||
'# StdIn, StdOut, StdErr Read and Write Pipes.
|
||||
dim as HANDLE StdInRd, StdOutRd, StdErrRd
|
||||
dim as HANDLE StdInWr, StdOutWr, StdErrWr
|
||||
dim merged as boolean
|
||||
|
||||
'# cmdline
|
||||
dim cmdline as string
|
||||
|
||||
'# assume start will fail
|
||||
result = false
|
||||
|
||||
if (running = false) then
|
||||
'# we should create the std* for the new proc!
|
||||
'# (like good parents, prepare everything!)
|
||||
|
||||
'# to ensure everything will work, we must allocate a console
|
||||
'# using AllocConsole, even if it fails.
|
||||
'# This solve the problems when running as service.
|
||||
'# we discard result of AllocConsole since we ALWAYS will allocate it.
|
||||
AllocConsole()
|
||||
|
||||
'# assume all the following steps succeed
|
||||
success = true
|
||||
|
||||
'# StdIn is the only std that will be created using pipes always
|
||||
'# StdIn
|
||||
if (CreatePipe(@StdInRd, @StdInWr, @proc_sa, 0) = 0) then
|
||||
success = false
|
||||
end if
|
||||
|
||||
'# Ensure the handles to the pipe are not inherited.
|
||||
if (SetHandleInformation(StdInWr, HANDLE_FLAG_INHERIT, 0) = 0) then
|
||||
success = false
|
||||
end if
|
||||
|
||||
'# StdOut and StdErr should be redirected?
|
||||
if (not _stdout_filename = "") or _
|
||||
(not _stderr_filename = "") then
|
||||
|
||||
'# out and err are the same? (merged)
|
||||
if (_stdout_filename = _stderr_filename) then
|
||||
merged = true
|
||||
end if
|
||||
end if
|
||||
|
||||
'# StdOut if stdout_filename
|
||||
if not (_stdout_filename = "") then
|
||||
StdOutWr = CreateFile(strptr(_stdout_filename), _
|
||||
GENERIC_WRITE, _
|
||||
FILE_SHARE_READ or FILE_SHARE_WRITE, _
|
||||
@proc_sa, _
|
||||
OPEN_ALWAYS, _
|
||||
FILE_ATTRIBUTE_NORMAL, _
|
||||
NULL)
|
||||
|
||||
if (StdOutWr = INVALID_HANDLE_VALUE) then
|
||||
'# failed to open file
|
||||
success = false
|
||||
else
|
||||
SetFilePointer(StdOutWr, 0, NULL, FILE_END)
|
||||
end if
|
||||
else
|
||||
'# use pipes instead
|
||||
'# StdOut
|
||||
if (CreatePipe(@StdOutRd, @StdOutWr, @proc_sa, 0) = 0) then
|
||||
success = false
|
||||
end if
|
||||
|
||||
if (SetHandleInformation(StdOutRd, HANDLE_FLAG_INHERIT, 0) = 0) then
|
||||
success = false
|
||||
end if
|
||||
end if 'not (_stdout_filename = "")
|
||||
|
||||
'# only create stderr if no merged.
|
||||
if (merged = true) then
|
||||
StdErrWr = StdOutWr
|
||||
else
|
||||
'# do the same for StdErr...
|
||||
if not (_stderr_filename = "") then
|
||||
StdErrWr = CreateFile(strptr(_stderr_filename), _
|
||||
GENERIC_WRITE, _
|
||||
FILE_SHARE_READ or FILE_SHARE_WRITE, _
|
||||
@proc_sa, _
|
||||
OPEN_ALWAYS, _
|
||||
FILE_ATTRIBUTE_NORMAL, _
|
||||
NULL)
|
||||
|
||||
if (StdErrWr = INVALID_HANDLE_VALUE) then
|
||||
'# failed to open file
|
||||
success = false
|
||||
else
|
||||
SetFilePointer(StdErrWr, 0, NULL, FILE_END)
|
||||
end if
|
||||
else
|
||||
'# use pipes instead
|
||||
'# StdOut
|
||||
if (CreatePipe(@StdErrRd, @StdErrWr, @proc_sa, 0) = 0) then
|
||||
success = false
|
||||
end if
|
||||
|
||||
if (SetHandleInformation(StdErrRd, HANDLE_FLAG_INHERIT, 0) = 0) then
|
||||
success = false
|
||||
end if
|
||||
|
||||
end if 'not (_stderr_filename = "")
|
||||
end if '(merged = true)
|
||||
|
||||
'# now we must proceed to create the process
|
||||
'# without the pipes, we shouldn't continue!
|
||||
if (success = true) then
|
||||
'# Set the Std* handles ;-)
|
||||
with context
|
||||
.cb = sizeof( context )
|
||||
.hStdError = StdErrWr
|
||||
.hStdOutput = StdOutWr
|
||||
.hStdInput = StdInRd
|
||||
.dwFlags = STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW
|
||||
'# FIXME: .wShowWindow = iif((_show_console = true), SW_SHOW, SW_HIDE)
|
||||
.wShowWindow = SW_HIDE
|
||||
end with
|
||||
|
||||
'# build the command line
|
||||
cmdline = _filename + " " + _arguments
|
||||
|
||||
'# now creates the process
|
||||
if (CreateProcess(NULL, _
|
||||
strptr(cmdline), _
|
||||
NULL, _
|
||||
NULL, _
|
||||
1, _ '# win32 TRUE (1)
|
||||
0, _
|
||||
NULL, _
|
||||
NULL, _
|
||||
@context, _
|
||||
@_process_info) = 0) then
|
||||
result = false
|
||||
else
|
||||
'# set the _pid
|
||||
_pid = _process_info.dwProcessId
|
||||
|
||||
'# OK? yeah, I think so.
|
||||
result = true
|
||||
|
||||
'# close the Std* handles
|
||||
CloseHandle(StdInRd)
|
||||
CloseHandle(StdInWr)
|
||||
CloseHandle(StdOutRd)
|
||||
CloseHandle(StdOutWr)
|
||||
CloseHandle(StdErrRd)
|
||||
CloseHandle(StdErrWr)
|
||||
|
||||
'# close children main Thread handle
|
||||
'CloseHandle(proc.hThread)
|
||||
'CloseHandle(proc.hProcess)
|
||||
|
||||
end if '# (CreateProcess() = 0)
|
||||
else
|
||||
result = false
|
||||
end if '# (success = TRUE)
|
||||
end if
|
||||
|
||||
return result
|
||||
end function
|
||||
|
||||
function ConsoleProcess.terminate(byval force as boolean = false) as boolean
|
||||
dim result as boolean
|
||||
dim success as boolean
|
||||
|
||||
dim proc as HANDLE
|
||||
dim code as uinteger
|
||||
dim wait_code as uinteger
|
||||
|
||||
'# is pid valid?
|
||||
if (running = true) then
|
||||
'# hook our custom console handler
|
||||
if not (SetConsoleCtrlHandler(@_console_handler, 1) = 0) then
|
||||
success = true
|
||||
end if
|
||||
|
||||
if (success = true) then
|
||||
'# get a handle to Process
|
||||
proc = _process_info.hProcess
|
||||
if not (proc = NULL) then
|
||||
'# process is valid, perform actions
|
||||
success = false
|
||||
|
||||
if not (force = true) then
|
||||
'# send CTRL_C_EVENT and wait for result
|
||||
if not (GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0) = 0) then
|
||||
'# it worked, wait 5 seconds terminates.
|
||||
wait_code = WaitForSingleObject(proc, 5000)
|
||||
if not (wait_code = WAIT_TIMEOUT) then
|
||||
success = true
|
||||
end if
|
||||
else
|
||||
success = false
|
||||
end if
|
||||
|
||||
'# Ctrl-C didn't work, try Ctrl-Break
|
||||
if (success = false) then
|
||||
'# send CTRL_BREAK_EVENT and wait for result
|
||||
if not (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0) = 0) then
|
||||
'# it worked, wait 5 seconds terminates.
|
||||
wait_code = WaitForSingleObject(proc, 5000)
|
||||
if not (wait_code = WAIT_TIMEOUT) then
|
||||
success = true
|
||||
end if
|
||||
else
|
||||
success = false
|
||||
end if
|
||||
end if
|
||||
|
||||
'# only do termination if force was set.
|
||||
elseif (force = true) and (success = false) then
|
||||
'# still no luck? we should do a hard kill then
|
||||
if (TerminateProcess(proc, 0) = 0) then
|
||||
success = false
|
||||
else
|
||||
success = true
|
||||
end if
|
||||
end if
|
||||
|
||||
'# now get process exit code
|
||||
if (success = true) then
|
||||
result = true
|
||||
else
|
||||
result = false
|
||||
end if
|
||||
else
|
||||
'# invalid process handler
|
||||
result = false
|
||||
end if
|
||||
|
||||
end if '# (success = true)
|
||||
|
||||
'# remove hooks
|
||||
if not (SetConsoleCtrlHandler(@_console_handler, 0) = 0) then
|
||||
success = true
|
||||
end if
|
||||
end if '# not (pid = 0)
|
||||
|
||||
return result
|
||||
end function
|
||||
|
||||
function ConsoleProcess._console_handler(byval dwCtrlType as DWORD) as BOOL
|
||||
dim result as BOOL
|
||||
|
||||
if (dwCtrlType = CTRL_C_EVENT) then
|
||||
result = 1
|
||||
elseif (dwCtrlType = CTRL_BREAK_EVENT) then
|
||||
result = 1
|
||||
end if
|
||||
|
||||
return result
|
||||
end function
|
Binary file not shown.
Loading…
Add table
Reference in a new issue