httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "William A. Rowe, Jr." <>
Subject RE: Platform Specific MPM Design Questions
Date Wed, 24 May 2000 02:25:34 GMT
> From: Tim Costello []
> Sent: Wednesday, May 24, 2000 6:38 AM
> On Tuesday, 23 May 2000, William A. Rowe, Jr. wrote:
> > 1) If this is the Win32 mpm, we need two arguments, -k and -n, which
> >    could be extracted from the argv/argc list, with the clean list
> >    retained for command argument parsing.  No special mpm arg_hook
> >    is required for alien arguments.
> So you want to put the command-line processing that deals 
> with service control
> into the MPM, 


> and you need the process_rec to get at the command line. Is this
> right so far? 


> Is ap_server_argv0 an alternative?

Ok... ap_server_argv0 is the display name of the process (short name).
In the Win32 service handler we are storing the service's 'name' instead,
since it appears in msgs as  Apache20Test: Error initializing arguments

the process->argv[0] is the full path of the executable.

I'm manipulating not only argv[0] but the entire args list.  An example
of launching service an NT service called Apache20Test would look like:

  C:\apache\apache.exe -k runserver

On the first pass we knock off -k runserver, tell the service manager
to start our service.  It calls the main() process over [more on that]
and the user started the service with -D DUMMYARG.  When the server
calls main() the arg list is 

  Apache20Test -D DUMMYARG

Having saved the original args... we combine the args into:

  C:\apache\apache.exe -k runserver -n Apache20Test -D DUMMYARG

We know we are a service, so we can drop -k runserver now.  We know
that -n Apache20Test has a configfile of C:\Test20\conf\httpd.conf,
so we save the service name, and reformat the args as 

  C:\apache\apache.exe -d C:\apache C:\Test20\conf\httpd.conf -D DUMMYARG

Finally we let the http_main.c main() process parse the args and start
the server.  In the less extreme case of a Win9x service, sames names and
parameters and all, the user launches the server with:

  C:\apache\apache.exe -k runserver -n Apache20Test -D DUMMYARG

Here there is no silly SCM and reentrant main(), so we simply save the 
server name, and leave the http_main.c main() process with the args:

  C:\apache\apache.exe -d C:\apache C:\Test20\conf\httpd.conf -D DUMMYARG

Simple enough?  No, I know it's a bear, but better that the service managers
and the mpm cooperate, and we kill alot of extra code in doing this.
> Also, dumb question #1 for today: what's an alien argument?

A command arg that a vanilla unix build wouldn't understand (-k, -n, -Zzz etc)

> > 2) If this is a WinNT service, something very odd needs to happen.
> > 
> >    On pass one, the Service Control Manager is invoked with Apache's
> >    main() function all over again.  The original main() code path
> >    never finishes, this is the end of it's life.  This will now be
> >    invoked by an internal -k runservice flag, rather than console 
> >    session tests.
> > 
> >    On the second pass, we replace argv[0] with the true argv[0]
> >    (since it is passed the service name by the SCM, rather than the
> >    executable name), and we insert -f and -d args from the Win32 
> >    service control registry.  (These CAN be overriden, however,
> >    when starting the service.)
> So how do you tell if you're running as a service in the 
> first place (ie. to
> set the -k runservice flag)? 

That's set up in the registry.  The SCM is told that the executable for
the service is "C:\Apache\Apache.exe" -k runservice.  The Win95 reg key
is told the same thing under Software/Windows/CurrentVersion/RunServices.

> What do you mean by "all over again" above? What came before 
> (this is pass one)? At the moment startup looks like:
>     * apache service started / exe invoked by SCM
>     * test to see if service - if so, do service stuff 
> (SetServiceStatus) as
>       well as everything else

Not much, I hope.  I want the MPM to interceed very early, so little memory
has been allocated and nothing is very solid.

[The more I promised above]:  A better solution, I have decided, is to
actually call out to the SCM, which will call back to the service's main()
proc.  What I HOPE to accomplish is to drop the execution back into the
same code stream.  The code looks like:

  http_main.c     main() calls
    mod_mpm_winnt   ap_hook_args() calls
      kernel32        StartService() calls
        mod_mpm_hookservice() which will set up a vector to return back into
                              the return vector of the ap_hook_args() call so
                              we resume execution exactly where we left off.
I haven't had to pull this shit since I was hacking on Motorola cpu's...
but it should be too bad.  The actual always terminates in an exit() call
anyway, so the thread won't pick back up where we left off.

> Can you outline what it will look like after the proposed changes?

I think I have above, but it isn't pretty.  The original thought was for the
ap_hook_args to launch the StartService to call back to the main() function,
and since we already went to the trouble to initialize the hooks, I'm 
thinking this is a cleaner (if not hairbrained) solution.

> > Everything else I am looking to move into the MPM can happen in the
> > ap_run_pre_config or ap_post_config_hook phase (depending). 
> > 
> > ap_run_pre_config phase will handle:
> > 
> >    -n servicename -k stop       {we don't care if the 
> config is valid}
> >    -n servicename -k uninstall  {we really don't care if 
> the config is valid :-}
> > 
> > ap_post_config_hook phase will handle:
> > 
> >    -n servicename -k runservice {internal Win9x only: show 
> the fools their errors}
> >    -n servicename -k restart    {no sense in restarting if 
> the config has errors}
> >    -n servicename -k start      {error out if trying to 
> launch with new errors on WinNT}
> >    -n servicename -k install    {be sure the config is 
> valid, at least at the moment :-)
> >    and process termination hooks for ^C/Close Window/Stop 
> Service/Shutdown etc...
> All right, I'm really confused now. You said above that -k 
> runservice would
> apply if it was a WinNT service, but just then "internal Win9x only". 

No, if the OS is WinNT, it interceeds right away.  If the OS is Win95,
we don't need to deal with it till the ap_run_pre_config phase :-)

> When you say "error out ... WinNT", a config error will 
> presumably cause the
> process to end. If this happens before we do SetServiceStatus(
> SERVICE_START_PENDING) then the SCM will hang, waiting for a 
> response. 

It does that to me often.  I hear you, though.  That's why we need
the WinNT service to start ASAP (before we start crunching args,
and hopefully before we try hooking other preloaded modules).

> What if someone tries to start the service using net start, 
> or the services
> applet in the control panel? Is this the NT -k runservice? 
> Re: previous
> question about detecting when apache is a service. 

Yes, because the ImagePath registry entry spells out the entire 
command:  "pathname/apache.exe" -k runservice 

> > I've spent many hours staring at these code paths... I 
> agree it's a hack, but
> > I need the environment prior to the command line parsing, 
> before much is 
> > initialized (since the NT service will loop).  But I think 
> all would like to
> > see every platform run with the same process sequence.  I'm 
> open to any
> > alternative suggestions.
> When I understand what the changes are, and how it might 
> work, I'll be more than happy to try suggesting something. 

Fair enough :-)  I'll have code later this week, with the new hook
everyone seems to prefer over process_rec* args to register_hooks.

> And Greg Stein said:
> > > I'm also looking at a way to hook in the NT service processing
> > > without the recursive call to main() (but with expanded argv[]).
> > > It will certainly involve a little bit of setjmp or stack
> > > manipulation, but I should be able to accomplish it.
> > 
> > Okay. That just sounds nasty. It seems that there *has* to 
> be a better way
> > to solve the problem than to use setjmp.
> I agree. I look forward to understanding the recursive main() bit. :-)

Recursive main() I hope won't happen.  Not if I can get return vectors to 
resume execution at the code step after launching the service.  Any good
examples would be appreciated.  [This does -not- have to be xplatform :-]

View raw message