On 6/24/05, abe-t <[EMAIL PROTECTED]> wrote:
> Update of /cvsroot/naviserver/naviserver/nsd
> In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16846/nsd
> 
> Modified Files:
>         nswin32.c
> Log Message:
>   Added provisions to fake that nsd as a service failed on Windows in order
>     for the Service Control Manager to restart it automatically.
> 
> 
> Index: nswin32.c
> ===================================================================
> RCS file: /cvsroot/naviserver/naviserver/nsd/nswin32.c,v
> retrieving revision 1.6
> retrieving revision 1.7
> diff -C2 -d -r1.6 -r1.7
> *** nswin32.c   13 Jun 2005 10:17:27 -0000      1.6
> --- nswin32.c   24 Jun 2005 08:40:27 -0000      1.7
> ***************
> *** 51,54 ****
> --- 51,55 ----
>   static void ExitService(void);
>   static char *GetServiceName(Ns_DString *dsPtr, char *server);
> + static int ReportException(int ec, char *msg);
>   static SERVICE_STATUS_HANDLE hStatus = 0;
>   static SERVICE_STATUS curStatus;
> ***************
> *** 57,60 ****
> --- 58,62 ----
>   static int tick;
>   static int sigpending;
> + static int servicefailed = 0;
> 
>   #define SysErrMsg() (NsWin32ErrMsg(GetLastError()))
> ***************
> *** 349,353 ****
>    */
> 
> ! void
>   NsHandleSignals(void)
>   {
> --- 351,355 ----
>    */
> 
> ! int
>   NsHandleSignals(void)
>   {
> ***************
> *** 388,391 ****
> --- 390,395 ----
>           StartTicker(SERVICE_STOP_PENDING);
>       }
> +
> +     return pending;
>   }
> 
> ***************
> *** 413,416 ****
> --- 417,421 ----
>       switch (sig) {
>       case NS_SIGTERM:
> +     case NS_SIGINT:
>       case NS_SIGHUP:
>           Ns_MutexLock(&lock);
> ***************
> *** 932,948 ****
>   ServiceMain(DWORD argc, LPTSTR *argv)
>   {
> !     hStatus = RegisterServiceCtrlHandler(argv[0], ServiceHandler);
> !     if (hStatus == 0) {
> !         Ns_Fatal("nswin32: RegisterServiceCtrlHandler() failed: '%s'",
> !                  SysErrMsg());
>       }
> -     curStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
> -     curStatus.dwServiceSpecificExitCode = 0;
> -     StartTicker(SERVICE_START_PENDING);
> -     Ns_Main(argc, argv, NULL);
> -     StopTicker();
> -     ReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 100);
> -     ReportStatus(SERVICE_STOPPED, 0, 0);
> -     Ns_Log(Notice, "nswin32: service exiting");
>   }
> 
> --- 937,964 ----
>   ServiceMain(DWORD argc, LPTSTR *argv)
>   {
> !     __try {
> !         hStatus = RegisterServiceCtrlHandler(argv[0], ServiceHandler);
> !         if (hStatus == 0) {
> !             Ns_Fatal("nswin32: RegisterServiceCtrlHandler() failed: '%s'",
> !                      SysErrMsg());
> !         }
> !         curStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
> !         curStatus.dwServiceSpecificExitCode = 0;
> !         StartTicker(SERVICE_START_PENDING);
> !         Ns_Main(argc, argv, NULL);
> !         StopTicker();
> !         ReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 100);
> !         if (!servicefailed) {
> !             ReportStatus(SERVICE_STOPPED, 0, 0);
> !         }
> !         Ns_Log(Notice, "nswin32: service exiting");
> !
> !         if(servicefailed) {
> !             exit(-1);
> !         }
> !     }
> !     __except (ReportException(GetExceptionCode(), "ServiceMain")) {
> !         // No code; this block is never executed.
>       }
>   }
> 
> ***************
> *** 1006,1009 ****
> --- 1022,1028 ----
>       curStatus.dwCurrentState = state;
>       curStatus.dwWin32ExitCode = code;
> +     if (code == ERROR_SERVICE_SPECIFIC_ERROR) {
> +         curStatus.dwServiceSpecificExitCode = code;
> +     }
>       curStatus.dwWaitHint = hint;
>       if (state == SERVICE_RUNNING || state == SERVICE_STOPPED) {
> ***************
> *** 1090,1091 ****
> --- 1109,1163 ----
>   }
> 
> +
> + /*
> +  *----------------------------------------------------------------------
> +  *
> +  * NsTclFailServiceObjCmd --
> +  *
> +  *    Tell the server not to unregister from the Service Control Manager
> +  *  (SCM) when exiting, effectively leaving SCM wondering about the
> +  *  service, thinking it failed and restarting it
> +  *  (provided restarting the serice is configured in SCM).
> +  *
> +  * Results:
> +  *    None.
> +  *
> +  *----------------------------------------------------------------------
> +  */
> +
> + int
> + NsTclFailServiceObjCmd(ClientData dummy, Tcl_Interp *interp, int argc, char 
> **argv)
> + {
> +     servicefailed = 1;
> +
> +     return TCL_OK;
> + }



This Windows only command asks for a restart, right?  This should be
hooked up to the -restart switch of the ns_shutdown command, which is
essentially the same thing.  Otherwise, Tcl programmers will have to
test the current platform to portably restart the server.




> + /*
> +  *----------------------------------------------------------------------
> +  *
> +  * reportException --
> +  *
> +  *    Handle expecptions - cause the server to terminate abruptly
> +  *    and leave a log trace. It is intended to prevents the default
> +  *    handling in Windows where a Window pops up and the user has to
> +  *    confirm - which then prevents the service control manager to
> +  *    restart the service. (The idea, however, does not seem to work
> +  *    as intended - Windows still brings up the popup for reporting
> +  *    the "bug" to Microsoft).
> +  *
> +  * Results:
> +  *    None.
> +  *
> +  * Side effects:
> +  *    Exits the server
> +  *
> +  *----------------------------------------------------------------------
> +  */
> +
> + static int ReportException(int ec, char *msg)
> + {
> +     fprintf(stderr, "EXCEPTION %x in %s\n", ec, msg); fflush(stderr);
> +     exit(-1);
> +     return EXCEPTION_EXECUTE_HANDLER;
> + }



If this is experimental debugging code it probably shouldn't be
committed to CVS.  It does look pretty experimental -- there's no way
this function will return a value after calling exit(), for example.

Reply via email to