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>