Changeset 391
- Timestamp:
- 11/20/06 10:05:34 (2 years ago)
- Files:
-
- branches/win32-native_service/projects/mongrel_service/native/mongrel_service.bas (modified) (7 diffs)
- branches/win32-native_service/projects/mongrel_service/native/mongrel_service.bi (modified) (2 diffs)
- branches/win32-native_service/projects/mongrel_service/native/process.bas (modified) (5 diffs)
- branches/win32-native_service/projects/mongrel_service/native/process.bi (modified) (1 diff)
- branches/win32-native_service/projects/mongrel_service/native/send_signal.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/win32-native_service/projects/mongrel_service/native/mongrel_service.bas
r377 r391 34 34 35 35 namespace mongrel_service 36 Function GetErrorString(ByVal Code As UInteger, ByVal MaxLen As UShort = 1024) As String 37 Dim ErrorString As Any PTR 38 Dim sError As String 39 Dim lLen As Integer 40 41 lLen = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM Or _ 42 FORMAT_MESSAGE_ALLOCATE_BUFFER, _ 43 NULL, _ 44 Code, _ 45 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), _ 46 @ErrorString, _ 47 MaxLen, _ 48 NULL) 49 50 If (ErrorString <> 0) Then 51 52 sError = Space(lLen - 2) 53 CopyMemory(StrPtr(sError), ByVal ErrorString, lLen-2) 54 55 LocalFree(ErrorString) 56 End If 57 58 Return sError 59 End Function 60 36 61 sub debug(byref message as string) 37 62 dim handle as integer … … 57 82 58 83 '# TODO: fix inheritance here 59 single_mongrel = @this84 single_mongrel_ref = @this 60 85 end constructor 61 86 … … 68 93 debug("single_onInit()") 69 94 95 '# due lack of inheritance, we use single_mongrel_ref as pointer to 96 '# SingleMongrel instance. now we should call StillAlive 97 self.StillAlive() 98 if (len(self.commandline) > 0) then 99 debug("starting child process with cmdline: " + self.commandline) 100 single_mongrel_ref->__child_pid = 0 101 single_mongrel_ref->__child_pid = spawn(self.commandline) 102 self.StillAlive() 103 debug("child process pid: " + str(single_mongrel_ref->__child_pid)) 104 end if 105 106 '# set as success, but we must evaluate this first! 107 result = -1 108 70 109 debug("single_onInit() done") 71 110 return result … … 74 113 sub single_onStart(byref self as ServiceProcess) 75 114 debug("single_onStart()") 115 116 do while (self.state = Running) or (self.state = Paused) 117 sleep 100 118 loop 119 76 120 debug("single_onStart() done") 77 121 end sub … … 79 123 sub single_onStop(byref self as ServiceProcess) 80 124 debug("single_onStop()") 125 126 '# now terminates the child process 127 if not (single_mongrel_ref->__child_pid = 0) then 128 debug("trying to kill pid: " + str(single_mongrel_ref->__child_pid)) 129 'if not (send_break(single_mongrel_ref->__child_pid) = 0) then 130 if not (terminate_spawned(single_mongrel_ref->__child_pid) = TRUE) then 131 debug("send_break() reported a problem when terminating process " + str(single_mongrel_ref->__child_pid)) 132 else 133 debug("child process terminated with success.") 134 end if 135 end if 136 81 137 debug("single_onStop() done") 82 138 end sub … … 88 144 "(c) 2006 The Mongrel development team.") 89 145 146 '# allocate a new console (this is for services 147 if (AllocConsole() = 0) then 148 debug("success in AllocConsole()") 149 else 150 debug("AllocConsole failed, error: " + GetErrorString(GetLastError())) 151 end if 152 153 '# we need to get the Console hook prior adding our handler. 154 if not (GetCtrlRoutineAddress() = 0) then 155 debug("error GetCtrlRoutineAddress()") 156 end if 157 90 158 '# add SingleMongrel (service) 91 159 host.Add(simple.__service) … … 93 161 '# call from Service Control Manager (SCM) 94 162 case RunAsService: 163 debug("ServiceHost RunAsService") 95 164 host.Run() 96 165 97 166 '# call from console, useful for debug purposes. 98 167 case RunAsConsole: 168 debug("ServiceController Console") 99 169 ctrl.Console() 100 170 branches/win32-native_service/projects/mongrel_service/native/mongrel_service.bi
r377 r391 33 33 #define SERVICEFB_INCLUDE_UTILS 34 34 #include once "lib/ServiceFB/ServiceFB.bi" 35 #include once "process.bi" 35 36 36 37 namespace mongrel_service … … 57 58 58 59 '# TODO: replace with inheritance here 59 dim shared single_mongrel as SingleMongrel ptr60 dim shared single_mongrel_ref as SingleMongrel ptr 60 61 end namespace branches/win32-native_service/projects/mongrel_service/native/process.bas
r378 r391 33 33 #include once "process.bi" 34 34 35 private sub _dprint(byref message as string) 36 dim handle as integer 37 38 handle = freefile 39 open EXEPATH + "\process.log" for append as #handle 40 41 print #handle, message 42 43 close #handle 44 end sub 45 35 46 function spawn(byref cmdLine as string) as uinteger 36 47 dim result as uinteger … … 52 63 '# StdIn 53 64 if (CreatePipe( @StdInRd, @StdInWr, @sa, 0 ) = 0) then 54 print "Error creating StdIn pipes."65 _dprint("Error creating StdIn pipes.") 55 66 end 0 56 67 end if … … 58 69 '# StdOut 59 70 if (CreatePipe( @StdOutRd, @StdOutWr, @sa, 0 ) = 0) then 60 print "Error creating StdOut pipes."71 _dprint("Error creating StdOut pipes.") 61 72 end 0 62 73 end if … … 64 75 '# StdErr 65 76 if (CreatePipe( @StdErrRd, @StdErrWr, @sa, 0 ) = 0) then 66 print "Error creating StdErr pipes."77 _dprint("Error creating StdErr pipes.") 67 78 end 0 68 79 end if … … 83 94 '// INIT 84 95 85 if (CreateProcess( NULL, _86 StrPtr( cmdLine), _96 if (CreateProcess(NULL, _ 97 StrPtr(cmdLine), _ 87 98 NULL, _ 88 99 NULL, _ 89 100 TRUE, _ 90 CREATE_NEW_PROCESS_GROUP or DETACHED_PROCESS, _101 CREATE_NEW_PROCESS_GROUP, _ '// CREATE_NEW_PROCESS_GROUP or DETACHED_PROCESS, _ 91 102 NULL, _ 92 103 NULL, _ 93 104 @si, _ 94 @pi ) = 0) then 105 @pi) = 0) then 106 _dprint("Error in CreateProcess (" + str(GetLastError())) 95 107 else 96 CloseHandle( pi.hProcess)97 CloseHandle( pi.hThread)108 CloseHandle(pi.hProcess) 109 CloseHandle(pi.hThread) 98 110 result = pi.dwProcessId 111 _dprint("Success in CreateProcess, PID " + str(result)) 99 112 end if 100 113 101 114 return result 102 115 end function 116 117 private function tricky_console_handler(byval dwCtrlType as DWORD) as BOOL 118 _dprint("tricky_console_handler got dwCtrlType = " + str(dwCtrlType)) 119 return (dwCtrlType = CTRL_C_EVENT) 120 end function 121 122 public function terminate_spawned(byval pid as uinteger) as BOOL 123 dim result as BOOL 124 125 result = FALSE 126 127 '# hook custom console_handler 128 SetConsoleCtrlHandler(@tricky_console_handler, TRUE) 129 130 '# fire CTRL_C_EVENT to all the children 131 if not (GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0) = 0) then 132 '# it worked 133 _dprint("GenerateConsoleCtrlEvent worked.") 134 result = TRUE 135 else 136 _dprint("GenerateConsoleCtrlEvent failed, error " + str(GetLastError())) 137 end if 138 139 '# we should check here if the pid no longer exist. 140 '# ... 141 142 '# remove our custom console handler 143 SetConsoleCtrlHandler(@tricky_console_handler, FALSE) 144 145 return result 146 end function branches/win32-native_service/projects/mongrel_service/native/process.bi
r378 r391 35 35 '# extern "C" from send_signal library 36 36 declare function send_break cdecl alias "send_break" (byval as uinteger) as integer 37 declare function GetCtrlRoutineAddress cdecl alias "GetCtrlRoutineAddress" () as uinteger 37 38 38 39 '# spawn(cmdline) => PID 39 40 declare function spawn(byref as string) as uinteger 41 declare function console_handler(byval as DWORD) as BOOL 42 declare function terminate_spawned(byval as uinteger) as BOOL branches/win32-native_service/projects/mongrel_service/native/send_signal.cpp
r376 r391 94 94 95 95 // inject the thread 96 printf("creating remote thread\n"); 96 97 hRemoteThread=CreateRemoteThread(hRemoteProc, NULL, 0, (LPTHREAD_START_ROUTINE)dwEntryPoint, (void *)CTRL_C_EVENT, CREATE_SUSPENDED, NULL); 97 98 if (NULL==hRemoteThread) { 99 printf("cannot create thread\n"); 98 100 _JumpLastError(rv, error, "CreateRemoteThread"); 99 101 } 100 102 101 103 // wake up the thread 104 printf("wake up thread\n"); 102 105 if (-1==ResumeThread(hRemoteThread)) { 106 printf("cannot wakeup thread\n"); 103 107 _JumpLastError(rv, error, "ResumeThread"); 104 108 } 105 109 106 110 // wait for the thread to finish 111 printf("waiting for signal...\n"); 107 112 if (WAIT_OBJECT_0!=WaitForSingleObject(hRemoteThread, INFINITE)) { 113 printf("error waitforsingleobject\n"); 108 114 _JumpLastError(rv, error, "WaitForSingleObject"); 109 115 } 110 116 111 117 // find out what happened 118 printf("get exit code.\n"); 112 119 if (!GetExitCodeThread(hRemoteThread, (DWORD *)&rv)) { 120 printf("GetExitCodeThread\n"); 113 121 _JumpLastError(rv, error, "GetExitCodeThread"); 114 122 } 115 123 124 printf("GetExitCodeThread = %d\n", rv); 116 125 if (STATUS_CONTROL_C_EXIT==rv) { 117 //printf("Target process was killed.\n");126 printf("Target process was killed.\n"); 118 127 rv=EXIT_OK; 119 128 } … … 254 263 255 264 //-------------------------------------------------------------------- 256 RETVAL GetCtrlRoutineAddress(void) {265 extern "C" RETVAL GetCtrlRoutineAddress(void) { 257 266 RETVAL rv=EXIT_OK; 258 267 … … 301 310 HANDLE hRemoteProc=NULL; 302 311 HANDLE hRemoteProcToken=NULL; 303 304 rv=GetCtrlRoutineAddress(); 305 _JumpIfError(rv, error, "GetCtrlRoutineAddress"); 306 307 // printf("Sending signal to process %d...\n", dwPid); 312 313 printf("send_break pid: %d\n", dwPid); 314 315 if (g_dwCtrlRoutineAddr==NULL) { 316 printf("getting CtrlRoutineAddress()...\n"); 317 rv=GetCtrlRoutineAddress(); 318 _JumpIfError(rv, error, "GetCtrlRoutineAddress"); 319 } 320 321 printf("Sending signal to process %d...\n", dwPid); 308 322 rv=AdvancedOpenProcess(dwPid, &hRemoteProc); 309 323 _JumpIfErrorStr(rv, error, "AdvancedOpenProcess", dwPid); 310 324 325 printf("Start remote thread...\n"); 311 326 rv=StartRemoteThread(hRemoteProc, g_dwCtrlRoutineAddr); 312 327 _JumpIfError(rv, error, "StartRemoteThread");
