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 03:17:42 GMT
> From: William A. Rowe, Jr. []
> Sent: Tuesday, May 23, 2000 9:26 PM
> [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.

Ok... I'm going to try an implementation within MPM that 
very, very roughly looks like:

static jmp_buf svcstart;
static int addt_argc;
static char const* const* addt_argv;
static char *service_name = NULL;
static char *signal = NULL;
void ap_rewrite_args(process_rec *p, int argc, char **argv)
    /* merge p->argv with rewrite_argv */

static void ap_post_config_hook(...
    if (ap_strcasecmp(signal, "runservice") && (osver == PLATFORM_WIN32_WINDOWS))
        /* Whew... got this far */
        /* set service flags, shutdown event handler, and free the console */
        return; /* to serve pages */

    /* And this is where we can trust the user to continue and... */
    if (ap_strcasecmp(signal, "start")) {
        /* On NT, a synonym for NET START service_name */

    if (ap_strcasecmp(signal, "restart")) {
        /* signal the running server */

    if (ap_strcasecmp(signal, "install")) {
        /* setup a new service */

static void ap_hook_args(process_rec *p)
    /* Parse args for -k signal, and -n service_name */
    if (ap_strcasecmp(signal, "runservice")) {
	  if (osver == PLATFORM_WIN32_WINNT) {
            if (!setjmp(svcstart)) {
		    /* call ServiceStart with the ntservice_entry starting point*/

                /* what?  we are still here?  We failed, so die. */
        /* read registry service args for -n svcname into svc_arg* */
        ap_rewriteargs(p, svc_argc, svc_argv);

        /* and again if WinNT service passed us more args */
	  if (osver == PLATFORM_WIN32_WINNT)
            ap_rewriteargs(p, addt_argc, addt_argv);

        return; /* into main() to really start Apache */

    if (!ap_strcasecmp(signal, "shutdown") || !ap_strcasecmp(signal, "stop")) {
        /* Signal the running server, stop is a worthwhile alias */

    if (!ap_strcasecmp(signal, "uninstall")) {
        /* Signal the running server, and rip out service_name from the system */
    /* And these are the only three signals we deal with here */

DWORD ntservice_entry(DWORD start_argc, char **start_argv)
    service_name = argv[0];
    addt_argc = start_argc;
    addt_argv = start_argv;
    longjmp(svcstart, TRUE);
    /* No, we -NEVER- return */

Nasty?  Probably not as nasty as what we do today.  This is an almost clean 
way to assure we don't have dozens of code paths for NT, 9x, service on NT, 
service on 9x etc...

BTW... I got here because NONE of my cleanup paths are ever executed in
main_win32.c or service.c, I was adding the atexit handlers and all that
rot instead, and finally got fed up with this tangled mess.


View raw message