You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2002/03/14 05:34:03 UTC

cvs commit: httpd-2.0/server/mpm/winnt mpm_winnt.c mpm_winnt.h service.c

wrowe       02/03/13 20:34:03

  Modified:    server/mpm/winnt mpm_winnt.c mpm_winnt.h service.c
  Log:
    My [sixth?] major revamp of service.c.  Traded an event for a mutex
    to the service_init completion, expanded timeouts, moved SERVICE_STOPPED
    message posting to the main thread since sometimes, in odd cirumstances,
    our SCM thread wasn't resumed prior to termination, and ripped the code
    for the stderr logs to use nt_eventlog.c instead.  And generally tried
    to make the code just a little bit more grokable [as if such a thing
    is really possible.]
  
  Revision  Changes    Path
  1.242     +4 -3      httpd-2.0/server/mpm/winnt/mpm_winnt.c
  
  Index: mpm_winnt.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm/winnt/mpm_winnt.c,v
  retrieving revision 1.241
  retrieving revision 1.242
  diff -u -r1.241 -r1.242
  --- mpm_winnt.c	14 Mar 2002 04:12:12 -0000	1.241
  +++ mpm_winnt.c	14 Mar 2002 04:34:03 -0000	1.242
  @@ -2069,10 +2069,10 @@
            * after logging begins, and the failure can land in the log.
            */
           if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
  -            service_to_start_success = mpm_service_to_start(&service_name);
  +            service_to_start_success = mpm_service_to_start(&service_name,
  +                                                            process->pool);
               if (service_to_start_success == APR_SUCCESS) {
                   service_set = APR_SUCCESS;
  -                ap_open_stderr_log(process->pool);
               }
           }
       }
  @@ -2270,7 +2270,8 @@
               {
                   if (osver.dwPlatformId != VER_PLATFORM_WIN32_NT) 
                   {
  -                    rv = mpm_service_to_start(&service_name);
  +                    rv = mpm_service_to_start(&service_name,
  +                                              server->process->pool);
                       if (rv != APR_SUCCESS) {
                           ap_log_error(APLOG_MARK,APLOG_ERR, rv, ap_server_conf,
                                        "%s: Unable to start the service manager.",
  
  
  
  1.34      +1 -1      httpd-2.0/server/mpm/winnt/mpm_winnt.h
  
  Index: mpm_winnt.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm/winnt/mpm_winnt.h,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- mpm_winnt.h	14 Mar 2002 04:19:00 -0000	1.33
  +++ mpm_winnt.h	14 Mar 2002 04:34:03 -0000	1.34
  @@ -96,7 +96,7 @@
   apr_status_t mpm_merge_service_args(apr_pool_t *p, apr_array_header_t *args, 
                                      int fixed_args);
   
  -apr_status_t mpm_service_to_start(const char **display_name);
  +apr_status_t mpm_service_to_start(const char **display_name, apr_pool_t *p);
   apr_status_t mpm_service_started(void);
   apr_status_t mpm_service_install(apr_pool_t *ptemp, int argc, 
                                   char const* const* argv);
  
  
  
  1.46      +67 -229   httpd-2.0/server/mpm/winnt/service.c
  
  Index: service.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm/winnt/service.c,v
  retrieving revision 1.45
  retrieving revision 1.46
  diff -u -r1.45 -r1.46
  --- service.c	13 Mar 2002 20:48:04 -0000	1.45
  +++ service.c	14 Mar 2002 04:34:03 -0000	1.46
  @@ -381,26 +381,33 @@
       
       if (globdat.hServiceStatus)
       {
  -        if (currentState == SERVICE_RUNNING)
  +        if (currentState == SERVICE_RUNNING) {
  +            globdat.ssStatus.dwWaitHint = 0;
  +            globdat.ssStatus.dwCheckPoint = 0;
               globdat.ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  -        else
  -	    globdat.ssStatus.dwControlsAccepted = 0;
  -        
  -        globdat.ssStatus.dwCurrentState = currentState;
  -        globdat.ssStatus.dwWin32ExitCode = exitCode;
  -        
  -        if ( ( currentState == SERVICE_RUNNING ) ||
  -             ( currentState == SERVICE_STOPPED ) )
  -        {
  +        }
  +        else if (currentState == SERVICE_STOPPED) {
               globdat.ssStatus.dwWaitHint = 0;
               globdat.ssStatus.dwCheckPoint = 0;
  +            if (!exitCode && globdat.ssStatus.dwCurrentState 
  +                                           != SERVICE_STOP_PENDING) {
  +                /* An unexpected exit?  Better to error! */
  +                exitCode = 1;
  +            }
  +            if (exitCode) {
  +                globdat.ssStatus.dwWin32ExitCode =ERROR_SERVICE_SPECIFIC_ERROR;
  +                globdat.ssStatus.dwServiceSpecificExitCode = exitCode;
  +            }
           }
  -        else
  -        {
  +        else {
  +            globdat.ssStatus.dwCheckPoint = ++checkPoint;
  +	    globdat.ssStatus.dwControlsAccepted = 0;
               if(waitHint)
                   globdat.ssStatus.dwWaitHint = waitHint;
  -            globdat.ssStatus.dwCheckPoint = ++checkPoint;
           }
  +
  +        globdat.ssStatus.dwCurrentState = currentState;
  +        
           rv = SetServiceStatus(globdat.hServiceStatus, &globdat.ssStatus);
       }
       return(rv);
  @@ -482,15 +489,13 @@
       if (dwCtrlCode == SERVICE_CONTROL_STOP)
       {
           ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
  -        globdat.ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
  -        ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 3000);
  +        ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 30000);
           return;
       }
       if (dwCtrlCode == SERVICE_APACHE_RESTART)
       {
           ap_signal_parent(SIGNAL_PARENT_RESTART);
  -        globdat.ssStatus.dwCurrentState = SERVICE_START_PENDING;
  -        ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 3000);
  +        ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 30000);
           return;
       }
       
  @@ -498,107 +503,6 @@
   }
   
   
  -long __stdcall service_stderr_thread(LPVOID hPipe)
  -{
  -    HANDLE hPipeRead = (HANDLE) hPipe;
  -    HANDLE hEventSource;
  -    char errbuf[256], *errread = errbuf;
  -    const char *errarg[9];
  -    DWORD errres;
  -    HKEY hk;
  -    
  -    errarg[0] = "The Apache service named";
  -    errarg[1] = mpm_display_name;
  -    errarg[2] = "reported the following error:\r\n>>>";
  -    errarg[3] = errbuf;
  -    errarg[4] = NULL;
  -    errarg[5] = NULL;
  -    errarg[6] = NULL;
  -    errarg[7] = NULL;
  -    errarg[8] = NULL;
  -    
  -    /* What are we going to do in here, bail on the user?  not. */
  -    if (!RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services"
  -                      "\\EventLog\\Application\\Apache Service", &hk)) 
  -    {
  -        /* The stock message file */
  -        char *netmsgkey = "%SystemRoot%\\System32\\netmsg.dll";
  -        DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | 
  -                       EVENTLOG_INFORMATION_TYPE; 
  - 
  -        RegSetValueEx(hk, "EventMessageFile", 0, REG_EXPAND_SZ,
  -                          (LPBYTE) netmsgkey, strlen(netmsgkey) + 1);
  -        
  -        RegSetValueEx(hk, "TypesSupported", 0, REG_DWORD,
  -                          (LPBYTE) &dwData, sizeof(dwData));
  -        RegCloseKey(hk);
  -    }
  -
  -    hEventSource = RegisterEventSource(NULL, "Apache Service");
  -
  -    while (ReadFile(hPipeRead, errread, 
  -                    sizeof(errbuf) - (errread - errbuf) - 1, &errres, NULL))
  -    {
  -        if (errres)
  -        {
  -            /* NULL terminate */
  -            errread[errres] = '\0';
  -
  -            /* Process complete lines */
  -            while (*errread) 
  -            {
  -                char *erreol;
  -                int errlen;
  -
  -                /* Trim leading whitespace */
  -                errread = errbuf;
  -                while (apr_isspace(*errread)) {
  -                    ++errread;
  -                }
  -                if (!*errread) {
  -                    errread = errbuf;
  -                    *errread = '\0';
  -                    continue;
  -                }
  -                /* Find eol, but only re-Read if the buffer is unfilled */
  -                erreol = strchr(errread, '\n');
  -                if (!erreol && (errread > errbuf)) {
  -                    errlen = strlen(errbuf);
  -                    memmove(errbuf, errread, errlen + 1);
  -                    errread = errbuf + errlen;
  -                    continue;
  -                }
  -                *erreol = '\0';
  -
  -                /* Generic message: '%1 %2 %3 %4 %5 %6 %7 %8 %9'
  -                 * The event code in netmsg.dll is 3299
  -                 */
  -                ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, 
  -                            3299, NULL, 9, 0, errarg, NULL);
  -                
  -                if (!erreol) {
  -                    errread = errbuf;
  -                    *errread = '\0';
  -                    continue;
  -                }
  -                errread = erreol + 1;
  -            }
  -        }
  -    }
  -
  -    if ((errres = GetLastError()) != ERROR_BROKEN_PIPE) {
  -        apr_snprintf(errbuf, sizeof(errbuf),
  -                     "Win32 error %d reading stderr pipe stream\r\n", 
  -                     GetLastError());
  -
  -        ReportEvent(hEventSource, EVENTLOG_ERROR_TYPE, 0, 
  -                    3299, NULL, 9, 0, errarg, NULL);
  -    }
  -    CloseHandle(hPipeRead);
  -    return 0;
  -}
  -
  -
   /* service_nt_main_fn is outside of the call stack and outside of the
    * primary server thread... so now we _really_ need a placeholder!
    * The winnt_rewrite_args has created and shared mpm_new_argv with us.
  @@ -607,20 +511,14 @@
   
   static void __stdcall service_nt_main_fn(DWORD argc, LPTSTR *argv)
   {
  -    HANDLE waitfor[2];
  -    HANDLE hPipeRead = NULL;
  -    HANDLE hPipeWrite = NULL;
  -    HANDLE hDup;
  -    HANDLE thread;
  -    DWORD  threadid;
       const char *ignored;
   
       /* args and service names live in the same pool */
       mpm_service_set_name(mpm_new_argv->pool, &ignored, argv[0]);
   
  +    memset(&globdat.ssStatus, 0, sizeof(globdat.ssStatus));
       globdat.ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
       globdat.ssStatus.dwCurrentState = SERVICE_START_PENDING;
  -    globdat.ssStatus.dwServiceSpecificExitCode = 0;
       globdat.ssStatus.dwCheckPoint = 1;
   
       if (!(globdat.hServiceStatus = RegisterServiceCtrlHandler(argv[0], service_nt_ctrl)))
  @@ -629,71 +527,9 @@
                        NULL, "Failure registering service handler");
           return;
       }
  +
       /* Report status, no errors, and buy 3 more seconds */
  -    ReportStatusToSCMgr(globdat.ssStatus.dwCurrentState, NO_ERROR, 3000);
  -    
  -    /* Create a pipe to send stderr messages to the system error log 
  -     */
  -    if (CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0)) 
  -    {
  -        HANDLE hProc = GetCurrentProcess();
  -        if (DuplicateHandle(hProc, hPipeWrite, hProc, &hDup,
  -                            0, TRUE, GENERIC_WRITE))
  -        {
  -            CloseHandle(hPipeWrite);
  -            hPipeWrite = hDup;
  -            thread = (HANDLE) _beginthreadex(NULL, 0, service_stderr_thread, 
  -                                             (LPVOID) hPipeRead, 0, &threadid);
  -            if (thread)
  -            {
  -                FILE *fl, flip;
  -                int fd;
  -
  -                CloseHandle(thread);
  -	
  -                /* Flush, commit and close stderr.  This is typically a noop
  -                 * in Win2K/XP since services start with NULL std handles,
  -                 * but is required for NT 4.0 and a decent saftey anyways.
  -                 */
  -                fflush(stderr);
  -                _commit(2 /* stderr */);
  -                fclose(stderr);
  -
  -                /* The fdopen mode "wcb" is write, binary, so that simple 
  -                 * strings are not buffered for \n -> crlf munging, and
  -                 * commit-on-write.  Used setvbuf to assure no buffering.
  -                 */
  -                if (((fd = _open_osfhandle((long) hPipeWrite, 
  -                                           _O_WRONLY | _O_BINARY) != -1)
  -                        && (dup2(fd, 2 /* stderr */) == 0)
  -                        && ((fl = _fdopen(2 /* stderr */, "wcb")) != NULL))) {
  -                    _close(fd);
  -                    flip = *stderr;
  -                    *stderr = *fl;
  -                    *fl = flip;
  -                    setvbuf(stderr, NULL, _IONBF, 0);
  -                }
  -
  -                /* The code above _will_ corrupt the StdHandle... 
  -                 * and we must do so anyways.  We set this up only
  -                 * after we initialized the posix stderr API.
  -                 */
  - 		SetStdHandle(STD_ERROR_HANDLE, hPipeWrite);
  -            }
  -            else
  -            {
  -                CloseHandle(hPipeRead);
  -                CloseHandle(hPipeWrite);
  -                hPipeWrite = NULL;
  -            }            
  -        }
  -        else
  -        {
  -            CloseHandle(hPipeRead);
  -            CloseHandle(hPipeWrite);
  -            hPipeWrite = NULL;
  -        }            
  -    }
  +    ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 30000);
   
       /* We need to append all the command arguments passed via StartService() 
        * to our running service... which just got here via the SCM...
  @@ -724,12 +560,7 @@
        */
       SetEvent(globdat.service_init);
   
  -    waitfor[0] = globdat.service_term;
  -    waitfor[1] = globdat.mpm_thread;
  -    WaitForMultipleObjects(2, waitfor, FALSE, INFINITE);
  -
  -    /* The process is ready to terminate, or already has */
  -    CloseHandle(hPipeWrite);
  +    WaitForSingleObject(globdat.service_term, INFINITE);
   }
   
   
  @@ -751,7 +582,6 @@
                        "Error starting service control dispatcher");
       }
   
  -    globdat.service_thread_id = 0;
       return (rv);
   }
   
  @@ -835,17 +665,22 @@
   
   void service_stopped(void)
   {
  +    DWORD rv;
  +
       /* Still have a thread & window to clean up, so signal now */
  -    if (globdat.service_thread_id)
  +    if (globdat.service_thread)
       {
           if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
           {
  -            ReportStatusToSCMgr(SERVICE_STOPPED,    // service state
  -                                NO_ERROR,           // exit code
  -                                0);                 // wait hint
  +            /* Stop logging to the event log */
  +            mpm_nt_eventlog_stderr_flush();
   
               /* Cause the service_nt_main_fn to complete */
  -            SetEvent(globdat.service_term);
  +            ReleaseMutex(globdat.service_term);
  +
  +            ReportStatusToSCMgr(SERVICE_STOPPED, // service state
  +                                NO_ERROR,        // exit code
  +                                0);              // wait hint
           }
           else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
           {
  @@ -859,12 +694,15 @@
   }
   
   
  -apr_status_t mpm_service_to_start(const char **display_name)
  +apr_status_t mpm_service_to_start(const char **display_name, apr_pool_t *p)
   {
       HANDLE hProc = GetCurrentProcess();
       HANDLE hThread = GetCurrentThread();
       HANDLE waitfor[2];
   
  +     /* GetCurrentThread returns a psuedo-handle, we need
  +      * a real handle for another thread to wait upon.
  +      */
       if (!DuplicateHandle(hProc, hThread, hProc, &(globdat.mpm_thread),
                            0, FALSE, DUPLICATE_SAME_ACCESS)) {
           return APR_ENOTHREAD;
  @@ -872,13 +710,16 @@
       
       if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
       {
  +        mpm_nt_eventlog_stderr_open(mpm_display_name, p);
  +
           globdat.service_init = CreateEvent(NULL, FALSE, FALSE, NULL);
  -        globdat.service_term = CreateEvent(NULL, FALSE, FALSE, NULL);
  -        if (globdat.service_init)
  -            globdat.service_thread = (HANDLE) _beginthreadex(NULL, 0, 
  -                                                  service_nt_dispatch_thread, 
  -                                                  NULL, 0, 
  -                                                  &globdat.service_thread_id);
  +        globdat.service_term = CreateMutex(NULL, TRUE, NULL);
  +        if (!globdat.service_init || !globdat.service_term) {
  +             return APR_EGENERAL;
  +        }
  +
  +        globdat.service_thread = CreateThread(NULL, 0, service_nt_dispatch_thread, 
  +                                              NULL, 0, &globdat.service_thread_id);
       }
       else /* osver.dwPlatformId != VER_PLATFORM_WIN32_NT */
       {
  @@ -886,31 +727,28 @@
               return GetLastError();
   
           globdat.service_init = CreateEvent(NULL, FALSE, FALSE, NULL);
  -        if (globdat.service_init)
  -            globdat.service_thread = (HANDLE) _beginthreadex(NULL, 0,
  -                                                  monitor_service_9x_thread, 
  -                                                  (LPVOID) mpm_service_name, 0,
  -                                                  &globdat.service_thread_id);
  +        if (!globdat.service_init) {
  +            return APR_EGENERAL;
  +        }
  +
  +        globdat.service_thread = CreateThread(NULL, 0, monitor_service_9x_thread, 
  +                                              (LPVOID) mpm_service_name, 0,
  +                                              &globdat.service_thread_id);
       }
   
  -    if (globdat.service_init && globdat.service_thread) 
  -    {
  -        waitfor[0] = globdat.service_init;
  -        waitfor[1] = globdat.service_thread;
  -    
  -        /* Wait for controlling thread init or termination */
  -        if (WaitForMultipleObjects(2, waitfor, FALSE, 10000) != WAIT_OBJECT_0) {
  -            CloseHandle(globdat.service_thread);
  -            CloseHandle(globdat.mpm_thread);
  -            return APR_ENOTHREAD;
  -        }
  +    if (!globdat.service_thread) {
  +        return APR_ENOTHREAD;
       }
   
  -    if (globdat.service_thread_id)
  -        atexit(service_stopped);
  -    else if (globdat.service_thread)
  -        CloseHandle(globdat.service_thread);
  +    waitfor[0] = globdat.service_init;
  +    waitfor[1] = globdat.service_thread;
  +
  +    /* Wait for controlling thread init or termination */
  +    if (WaitForMultipleObjects(2, waitfor, FALSE, 10000) != WAIT_OBJECT_0) {
  +        return APR_ENOTHREAD;
  +    }
   
  +    atexit(service_stopped);
       *display_name = mpm_display_name; 
       return APR_SUCCESS;
   }
  @@ -934,7 +772,7 @@
       if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
           ReportStatusToSCMgr(SERVICE_STOP_PENDING, // service state
                               NO_ERROR,             // exit code
  -                            3000);                // wait hint
  +                            30000);               // wait hint
   }
   
   
  
  
  

Re: cvs commit: httpd-2.0/server/mpm/winnt mpm_winnt.c mpm_winnt.h service.c

Posted by Bill Stoddard <bi...@wstoddard.com>.
c mpm_winnt.h service.c


> At 12:07 PM 3/14/2002, you wrote:
> >Bill, does this resolve the Win32 showstoppers? Specifically...
> >
> >   * Address popular PRs
> >         * Win32 doesn't install as service correctly [9863, 9914, 9961]
> >         * Don't be stupid and cd to a blank directory when doing installs
> >           [PR 9993]
> >
> >I'll not be too keen on Win32 holding up a beta.
> 
> No, this doesn't fix those showstoppers.  They actually don't belong
> in httpd-2.0/STATUS in the first place.  They are part of the installer,
> not core, and belong in httpd-win32-msi/STATUS.
> 
> And they can be fixed even after a 2.0.x is made beta-ready, since
> the tag on httpd-win32-msi is independent of httpd-2.0/apr/apr-util.

That's what I thought. Cool!

Bill


Re: cvs commit: httpd-2.0/server/mpm/winnt mpm_winnt.c mpm_winnt.h service.c

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 12:07 PM 3/14/2002, you wrote:
>Bill, does this resolve the Win32 showstoppers? Specifically...
>
>   * Address popular PRs
>         * Win32 doesn't install as service correctly [9863, 9914, 9961]
>         * Don't be stupid and cd to a blank directory when doing installs
>           [PR 9993]
>
>I'll not be too keen on Win32 holding up a beta.

No, this doesn't fix those showstoppers.  They actually don't belong
in httpd-2.0/STATUS in the first place.  They are part of the installer,
not core, and belong in httpd-win32-msi/STATUS.

And they can be fixed even after a 2.0.x is made beta-ready, since
the tag on httpd-win32-msi is independent of httpd-2.0/apr/apr-util.

Bill


Re: cvs commit: httpd-2.0/server/mpm/winnt mpm_winnt.c mpm_winnt.h service.c

Posted by Bill Stoddard <bi...@wstoddard.com>.
Bill, does this resolve the Win32 showstoppers? Specifically...

  * Address popular PRs
        * Win32 doesn't install as service correctly [9863, 9914, 9961]
        * Don't be stupid and cd to a blank directory when doing installs
          [PR 9993]

I'll not be too keen on Win32 holding up a beta.

Bill

----- Original Message ----- 
From: <wr...@apache.org>
To: <ht...@apache.org>
Sent: Wednesday, March 13, 2002 11:34 PM
Subject: cvs commit: httpd-2.0/server/mpm/winnt mpm_winnt.c mpm_winnt.h service.c


> wrowe       02/03/13 20:34:03
> 
>   Modified:    server/mpm/winnt mpm_winnt.c mpm_winnt.h service.c
>   Log:
>     My [sixth?] major revamp of service.c.  Traded an event for a mutex
>     to the service_init completion, expanded timeouts, moved SERVICE_STOPPED
>     message posting to the main thread since sometimes, in odd cirumstances,
>     our SCM thread wasn't resumed prior to termination, and ripped the code
>     for the stderr logs to use nt_eventlog.c instead.  And generally tried
>     to make the code just a little bit more grokable [as if such a thing
>     is really possible.]
>