You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by jf...@apache.org on 2002/02/17 23:14:43 UTC
cvs commit: jakarta-tomcat-service/native/winnt/moni vdmonisvc.c
jfclere 02/02/17 14:14:43
Modified: native/winnt/moni vdmonisvc.c
Log:
Arrange the shutdown for win9x.
Revision Changes Path
1.5 +178 -65 jakarta-tomcat-service/native/winnt/moni/vdmonisvc.c
Index: vdmonisvc.c
===================================================================
RCS file: /home/cvs/jakarta-tomcat-service/native/winnt/moni/vdmonisvc.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- vdmonisvc.c 16 Feb 2002 22:57:51 -0000 1.4
+++ vdmonisvc.c 17 Feb 2002 22:14:42 -0000 1.5
@@ -12,6 +12,7 @@
#include <windows.h>
+#include <winuser.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
@@ -26,6 +27,8 @@
SERVICE_STATUS ssStatus;
SERVICE_STATUS_HANDLE sshStatusHandle;
DWORD dwErr;
+HANDLE hServerStopEvent = NULL;
+HANDLE hMonitorProcess = NULL;
/*
* NT/other detection
@@ -68,9 +71,9 @@
hEventSource = NULL;
#ifdef CYGWIN
- sprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
+ sprintf(szMsg, TEXT("%s ERROR: %d"), TEXT(SZSERVICENAME), dwErr);
#else
- _stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
+ _stprintf(szMsg, TEXT("%s ERROR: %d"), TEXT(SZSERVICENAME), dwErr);
#endif
lpszStrings[0] = szMsg;
lpszStrings[1] = lpszMsg;
@@ -98,25 +101,178 @@
time( &long_time );
newtime = localtime( &long_time );
-
- fprintf(log,"%.24s:%s: %s\n",asctime(newtime),szMsg, lpszMsg);
+ if (dwErr)
+ fprintf(log,"%.24s:%s: %s\n",asctime(newtime),szMsg, lpszMsg);
+ else
+ fprintf(log,"%.24s: %s\n",asctime(newtime), lpszMsg);
fclose(log);
}
}
}
+//
+// FUNCTION: ServiceStop
+//
+// PURPOSE: Stops the service
+//
+// PARAMETERS:
+// none
+//
+// RETURN VALUE:
+// none
+//
+// COMMENTS:
+// If a ServiceStop procedure is going to
+// take longer than 3 seconds to execute,
+// it should spawn a thread to execute the
+// stop code, and return. Otherwise, the
+// ServiceControlManager will believe that
+// the service has stopped responding.
+//
+VOID ServiceStop()
+{
+ if ( hServerStopEvent )
+ SetEvent(hServerStopEvent);
+}
+
+/*
+ * Wait for the monitor process to stop
+ */
+int WaitForMonitor(int num)
+{
+ DWORD qreturn;
+ int i;
+
+ for (i=0;i<num;i++) {
+ if (hMonitorProcess == NULL) break;
+ if (GetExitCodeProcess(hMonitorProcess, &qreturn)) {
+ if (qreturn == STILL_ACTIVE) {
+ Sleep(1000);
+ continue;
+ }
+ hMonitorProcess = NULL;
+ break;
+ }
+ break;
+ }
+ if (i==num)
+ return -1;
+ return 0;
+}
/* This group of functions are provided for the service/console app
* to register itself a HandlerRoutine to accept tty or service messages
* adapted from src/os/win32/Win9xConHook.c (httpd-1.3!).
*/
-/* Exported function that creates a Win9x 'service' via a hidden window,
- * that notifies the process via the HandlerRoutine messages.
+/* This is the WndProc procedure for our invisible window.
+ * When our subclasssed tty window receives the WM_CLOSE, WM_ENDSESSION,
+ * or WM_QUERYENDSESSION messages, the message is dispatched to our hidden
+ * window (this message process), and we call the installed HandlerRoutine
+ * that was registered by the app.
+ */
+#ifndef ENDSESSION_LOGOFF
+#define ENDSESSION_LOGOFF 0x80000000
+#endif
+static LRESULT CALLBACK ttyConsoleCtrlWndProc(HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam)
+{
+ int qreturn;
+ if (msg == WM_CREATE) {
+ AddToMessageLog(TEXT("ttyConsoleCtrlWndProc WM_CREATE"));
+ return 0;
+ } else if (msg == WM_DESTROY) {
+ AddToMessageLog(TEXT("ttyConsoleCtrlWndProc WM_DESTROY"));
+ return 0;
+ } else if (msg == WM_CLOSE) {
+ // Call StopService?.
+ AddToMessageLog(TEXT("ttyConsoleCtrlWndProc WM_CLOSE"));
+ return 0; // May return 1 if StopService failed.
+ } else if ((msg == WM_QUERYENDSESSION) || (msg == WM_ENDSESSION)) {
+ if (lParam & ENDSESSION_LOGOFF) {
+ // Here we have nothing to our hidden windows should stay.
+ AddToMessageLog(TEXT("ttyConsoleCtrlWndProc LOGOFF"));
+ return(1); // Otherwise it cancels the logoff
+ } else {
+ // Stop Service.
+ AddToMessageLog(TEXT("ttyConsoleCtrlWndProc SHUTDOWN"));
+ ServiceStop();
+
+ // Wait until it stops.
+ qreturn = WaitForMonitor(3);
+
+ if (msg == WM_QUERYENDSESSION) {
+ AddToMessageLog(
+ TEXT("ttyConsoleCtrlWndProc SHUTDOWN (query)"));
+ if (qreturn) {
+ AddToMessageLog(
+ TEXT("Cancelling shutdown: cannot stop service"));
+ return(0);
+ }
+ } else
+ AddToMessageLog(TEXT("ttyConsoleCtrlWndProc SHUTDOWN"));
+ return(1); // Otherwise it cancels the shutdown.
+ }
+ }
+ return (DefWindowProc(hwnd, msg, wParam, lParam));
+}
+/* ttyConsoleCreateThread is the process that runs within the user app's
+ * context. It creates and pumps the messages of a hidden monitor window,
+ * watching for messages from the system, or the associated subclassed tty
+ * window. Things can happen in our context that can't be done from the
+ * tty's context, and visa versa, so the subclass procedure and this hidden
+ * window work together to make it all happen.
+ */
+static DWORD WINAPI ttyConsoleCtrlThread()
+{
+ HWND monitor_hwnd;
+ WNDCLASS wc;
+ MSG msg;
+ wc.style = CS_GLOBALCLASS;
+ wc.lpfnWndProc = ttyConsoleCtrlWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 8;
+ wc.hInstance = NULL;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "ApacheJakartaService";
+
+ if (!RegisterClass(&wc)) {
+ AddToMessageLog(TEXT("RegisterClass failed"));
+ return 0;
+ }
+
+ /* Create an invisible window */
+ monitor_hwnd = CreateWindow(wc.lpszClassName,
+ "ApacheJakartaService",
+ WS_OVERLAPPED & ~WS_VISIBLE,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL,
+ GetModuleHandle(NULL), NULL);
+
+ if (!monitor_hwnd) {
+ AddToMessageLog(TEXT("RegisterClass failed"));
+ return 0;
+ }
+
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ return 0;
+}
+/*
+ * Register the process to resist logoff and start the thread that will receive
+ * the shutdown via a hidden window.
*/
-BOOL __declspec(dllexport) WINAPI Windows9xServiceCtrlHandler(
- PHANDLER_ROUTINE phandler,
- LPCSTR name)
+BOOL Windows9xServiceCtrlHandler()
{
+ HANDLE hThread;
+ DWORD tid;
HINSTANCE hkernel;
DWORD (WINAPI *register_service_process)(DWORD, DWORD) = NULL;
@@ -145,28 +301,13 @@
/*
* To be handle notice the shutdown, we need a thread and window.
*/
-/*
- if (name)
- {
- DWORD tid;
- HANDLE hThread;
- static tty_info tty; // Must be static, because we are going to return.
- tty.instance = GetModuleHandle(NULL);
- tty.phandler = phandler;
- tty.parent = NULL;
- tty.name = name;
- tty.type = 2;
- RegisterWindows9xService(TRUE);
- hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
- (LPVOID)&tty, 0, &tid);
- if (hThread)
- {
- CloseHandle(hThread);
- return TRUE;
- }
- }
- return FALSE;
- */
+ hThread = CreateThread(NULL, 0, ttyConsoleCtrlThread,
+ (LPVOID)NULL, 0, &tid);
+ if (hThread) {
+ CloseHandle(hThread);
+ return TRUE;
+ }
+ AddToMessageLog(TEXT("jsvc shutdown listener start failed"));
return TRUE;
}
@@ -232,12 +373,6 @@
return(1);
}
-// this event is signalled when the
-// service should end
-//
-HANDLE hServerStopEvent = NULL;
-
-
//
// FUNCTION: ServiceStart
//
@@ -327,6 +462,7 @@
AddToMessageLog(TEXT("ServiceStart: jsvc started"));
CloseHandle(ProcessInformation.hThread);
ProcessInformation.hThread = NULL;
+ hMonitorProcess = ProcessInformation.hProcess;
if (!ReportManager(SERVICE_START_PENDING))
goto cleanup;
@@ -368,6 +504,7 @@
if (qreturn == STILL_ACTIVE) continue;
}
AddToMessageLog(TEXT("ServiceStart: jsvc crashed"));
+ hMonitorProcess = NULL;
CloseHandle(hServerStopEvent);
CloseHandle(ProcessInformation.hProcess);
exit(0); // exit ungracefully so
@@ -385,6 +522,7 @@
AddToMessageLog(TEXT("ServiceStart: jsvc stop failed"));
break;
}
+ WaitForMonitor(6);
AddToMessageLog(TEXT("ServiceStart: jsvc stopped"));
break; // finished!!!
}
@@ -399,32 +537,6 @@
CloseHandle(ProcessInformation.hProcess);
}
-
-
-//
-// FUNCTION: ServiceStop
-//
-// PURPOSE: Stops the service
-//
-// PARAMETERS:
-// none
-//
-// RETURN VALUE:
-// none
-//
-// COMMENTS:
-// If a ServiceStop procedure is going to
-// take longer than 3 seconds to execute,
-// it should spawn a thread to execute the
-// stop code, and return. Otherwise, the
-// ServiceControlManager will believe that
-// the service has stopped responding.
-//
-VOID ServiceStop()
-{
- if ( hServerStopEvent )
- SetEvent(hServerStopEvent);
-}
//
@@ -570,9 +682,10 @@
AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));
return;
}
+ AddToMessageLog(TEXT("StartService started"));
} else {
- Windows9xServiceCtrlHandler(service_ctrl,TEXT(SZSERVICENAME));
+ Windows9xServiceCtrlHandler();
ServiceStart(argc,argv);
+ AddToMessageLog(TEXT("StartService stopped"));
}
- AddToMessageLog(TEXT("StartService started"));
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>