You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by st...@hyperreal.org on 2000/02/14 23:01:12 UTC

cvs commit: apache-2.0/src/os/win32 main_win32.c

stoddard    00/02/14 14:01:11

  Modified:    src/main http_main.c
               src/modules/mpm/winnt winnt.c
               src/os/win32 main_win32.c
  Log:
  Rework the code to handle apache -k shutdown|restart. The fundamental problem
  being solved here is determining the best way to discover the Apache
  parent process PID (stored in the location specified by the PidFile directive).
  This patch attempts to read the config file directly to determine the
  pidfile and avoids going through the motions of calling all the module initialization
  routines.
  
  This patch will not work if the pidfile directive is in a file pointed to by
  an include directive. Not sure is this is a common case or not on Windows.
  If it is, it is easy enough to add a bit more code to follow include
  directives. An interesting modification would be to detect the presence of a \
  -C directive containing a pointer to the pidfile: E.g.,
  apache -k restart -C "pidfile d:/mypidfile". Let's keep it simple for now and
  see what happens.
  
  Revision  Changes    Path
  1.29      +0 -15     apache-2.0/src/main/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/http_main.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- http_main.c	2000/02/03 19:38:08	1.28
  +++ http_main.c	2000/02/14 22:01:04	1.29
  @@ -298,10 +298,6 @@
       ap_context_t *ptemp; /* Pool for temporary config stuff, reset often */
       ap_context_t *pcommands; /* Pool for -C and -c switches */
   
  -#ifdef WIN32
  -    char *signal = NULL;
  -#endif
  -
       ap_server_argv0 = process->short_name;
       
       ap_util_uri_init();
  @@ -334,11 +330,6 @@
   	case 'f':
   	    confname = ap_optarg;
   	    break;
  -#ifdef WIN32
  -        case 'k':
  -	    signal = ap_optarg;
  -            break;
  -#endif
   	case 'v':
   	    printf("Server version: %s\n", ap_get_server_version());
   	    printf("Server built:   %s\n", ap_get_server_built());
  @@ -377,12 +368,6 @@
   	ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Syntax OK\n");
   	destroy_and_exit_process(process, 0);
       }
  -#ifdef WIN32
  -    if (signal) {
  -        ap_signal_parent(pconf, signal, ap_server_root);
  -        destroy_and_exit_process(process, 0);
  -    }
  -#endif
       ap_clear_pool(plog);
       ap_run_open_logs(pconf, plog, ptemp, server_conf);
       ap_post_config_hook(pconf, plog, ptemp, server_conf);
  
  
  
  1.39      +0 -55     apache-2.0/src/modules/mpm/winnt/winnt.c
  
  Index: winnt.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/mpm/winnt/winnt.c,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- winnt.c	2000/02/14 14:28:16	1.38
  +++ winnt.c	2000/02/14 22:01:08	1.39
  @@ -359,61 +359,6 @@
   {
       signal_parent(0);
   }
  -
  -void ap_signal_parent(ap_context_t *p, const char* signal, 
  -                      const char* server_root) 
  -{
  -    HANDLE event;
  -    char prefix[20];
  -    char *EventName;
  -    FILE *fp;
  -    int nread;
  -    char *fname;
  -    int end;
  -
  -    printf("signal = %s\n", signal);
  -
  -    fname = ap_server_root_relative (p, ap_pid_fname);
  -
  -    fp = fopen(fname, "r");
  -    if (!fp) {
  -	printf("Cannot read apache PID file %s. Error = %d\n", fname, errno);
  -        return;
  -    }
  -    prefix[0] = 'a';
  -    prefix[1] = 'p';
  -
  -    nread = fread(prefix+2, 1, sizeof(prefix)-3, fp);
  -    if (nread == 0) {
  -	fclose(fp);
  -	printf("PID file %s was empty\n", fname);
  -        return;
  -    }
  -    fclose(fp);
  -
  -    /* Terminate the prefix string */
  -    end = 2 + nread - 1;
  -    while (end > 0 && (prefix[end] == '\r' || prefix[end] == '\n'))
  -	end--;
  -    prefix[end + 1] = '\0';
  -
  -    /* Build the event name. Should be one of the following...
  -     * apPID_shutdown
  -     * apPID_restart
  -     */
  -    EventName = ap_pstrcat(p,prefix,"_",signal,NULL);
  -    printf("event name = %s\n", EventName);
  -    event = OpenEvent(EVENT_ALL_ACCESS, FALSE, EventName);
  -    printf("event handle = %d\n", event);
  -    if (event == NULL) {
  -	printf("Unable to open event %s.\n", EventName);
  -        return;
  -    }
  -    SetEvent(event);
  -    ResetEvent(event);
  -    CloseHandle(event);
  -    return;
  -}
   /*
    * Initialise the signal names, in the global variables signal_name_prefix, 
    * signal_restart_name and signal_shutdown_name.
  
  
  
  1.7       +89 -6     apache-2.0/src/os/win32/main_win32.c
  
  Index: main_win32.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/os/win32/main_win32.c,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- main_win32.c	2000/02/09 22:16:24	1.6
  +++ main_win32.c	2000/02/14 22:01:10	1.7
  @@ -77,6 +77,84 @@
   __declspec(dllexport) int apache_main(int argc, char *argv[]);
   #define DEFAULTSERVICENAME "Apache"
   
  +static const char* read_config_cmd(char *filename, char *cmd, ap_context_t *p)
  +{
  +    ap_status_t rc;
  +    char l[MAX_STRING_LEN];
  +    const char *args, *cmd_name;
  +    const char *s = NULL;
  +    configfile_t *config_file = NULL;
  +
  +    rc = ap_pcfg_openfile(&config_file, p, filename);
  +    if (rc != APR_SUCCESS) {
  +        printf("Apache: Unable to open %s.\n", filename);
  +        return NULL;
  +    }
  +    while (!(ap_cfg_getline(l, MAX_STRING_LEN, config_file))) {
  +        if ((l[0] == '#') || (!l[0]))
  +            continue;
  +        args = l;
  +        cmd_name = ap_getword_conf(p, &args);
  +        if (!stricmp(cmd_name,cmd)) {
  +            s = args;
  +            break;
  +        }
  +    }
  +    ap_cfg_closefile(config_file);
  +    if (s == NULL) {
  +        printf("Apache: Did not find directive %s in %s.\n", cmd, filename);
  +    }
  +    return s;
  +}
  +static void signal_parent(const char* file, const char* signal, 
  +                          ap_context_t *p) 
  +{
  +    HANDLE event;
  +    char prefix[20];
  +    char *EventName;
  +    FILE *fp;
  +    int nread;
  +    int end;
  +    fp = fopen(file, "r");
  +    if (!fp) {
  +	printf("Cannot read apache PID file %s. Error = %d\n", file, errno);
  +        return;
  +    }
  +    prefix[0] = 'a';
  +    prefix[1] = 'p';
  +
  +    nread = fread(prefix+2, 1, sizeof(prefix)-3, fp);
  +    if (nread == 0) {
  +	fclose(fp);
  +	printf("PID file %s was empty\n", file);
  +        return;
  +    }
  +    fclose(fp);
  +
  +    /* Terminate the prefix string */
  +    end = 2 + nread - 1;
  +    while (end > 0 && (prefix[end] == '\r' || prefix[end] == '\n'))
  +	end--;
  +    prefix[end + 1] = '\0';
  +
  +    /* Build the event name. Should be one of the following...
  +     * apPID_shutdown
  +     * apPID_restart
  +     */
  +    EventName = ap_pstrcat(p,prefix,"_",signal,NULL);
  +    printf("event name = %s\n", EventName);
  +    event = OpenEvent(EVENT_ALL_ACCESS, FALSE, EventName);
  +    printf("event handle = %d\n", event);
  +    if (event == NULL) {
  +	printf("Unable to open event %s.\n", EventName);
  +        return;
  +    }
  +    SetEvent(event);
  +    ResetEvent(event);
  +    CloseHandle(event);
  +    return;
  +    
  +}
   int main(int argc, char *argv[])
   {
       ap_context_t *pwincmd;
  @@ -220,13 +298,18 @@
           exit(0);
       }
   
  -    /* Let http_main handle -k restart|shutdown */
  +    /* Handle -k restart|shutdown */
       if (signal && strcasecmp(signal, "start")) {
  -        new = (char **) ap_push_array(cmdtbl);
  -        *new = "-k";
  -        new = (char **) ap_push_array(cmdtbl);
  -        *new = signal;
  -        new_argc += 2;    
  +        char *s;
  +        s = read_config_cmd(server_confname, "pidfile", pwincmd);
  +        if (s == NULL) {
  +            exit(0);
  +        }
  +        if (!ap_os_is_path_absolute(s)) {
  +            s = ap_make_full_path(pwincmd, server_root, s);
  +        }
  +        signal_parent(s, signal, pwincmd);
  +        exit(0);
       }
   
       /* Complete building the new argv list. Need to add:
  
  
  

RE: cvs commit: apache-2.0/src/os/win32 main_win32.c

Posted by "William A. Rowe, Jr." <wr...@lnd.com>.
> > Are you using
> > WaitForObjects (and therefore able to wait on a mutex)?
> apache -k restart
> > would simply signal the named mutex.
>
> Yep, that's exacty how it works.  The parent PID is part of
> the name in the
> named mutex. The preferred way to run multiple processes is
> to run them as
> services. So, an apache -k restart -n servicename should work
> to restart a
> particular service. It's broken in Apache 1.3 & 2.0. It is
> possible to run
> multiple Apache's from the command line by passing in serverroot and
> serverconf on the command line.  Keeping track of each of the
> parent PIDs in
> the registry would be difficult in this case.

Agreed, while we could create a volatile registry key, that has it's own
repercussions...

But if we are facing multiple serverconf args, why not create a
serverconf.pid file in the same folder?

Alternately, since this is dynamic, how about the following (very sketchy)
idea;

dword /* pid */ ap_query_parent(dword anypid, char *servicenamebuffer)

which resolves anypid to the main apache thread pid, and then returns the
servicename, documentroot etc... in order to match the desired thread to
manipulate.  Then for enumerating... something like...

dword /* pid */ ap_enum_apache(void **enumblock /* initially passed as
NULL*/ )
void ap_end_enum_apache(void **enumblock /* initially passed as NULL*/ )

So how do we devolve the info from the thread pool?  Any apache.exe child
resolves to an apache.exe parent.  Ergo, if the parent differs, we have a
top apache thread.  How do we handle ap_query_apache?  Add another event
along the same lines as ap##_shutdown et al.

Excuse if I've got it all upside down, I havn't begun looking at Apache's
mutex and thread handling (yet...)

Just food for thought

Bill


Re: cvs commit: apache-2.0/src/os/win32 main_win32.c

Posted by Bill Stoddard <st...@raleigh.ibm.com>.
> Are you using
> WaitForObjects (and therefore able to wait on a mutex)? apache -k restart
> would simply signal the named mutex.
Yep, that's exacty how it works.  The parent PID is part of the name in the
named mutex. The preferred way to run multiple processes is to run them as
services. So, an apache -k restart -n servicename should work to restart a
particular service. It's broken in Apache 1.3 & 2.0. It is possible to run
multiple Apache's from the command line by passing in serverroot and
serverconf on the command line.  Keeping track of each of the parent PIDs in
the registry would be difficult in this case.

Bill


Re: cvs commit: apache-2.0/src/os/win32 main_win32.c

Posted by Greg Stein <gs...@lyra.org>.
On Tue, 15 Feb 2000, Bill Stoddard wrote:
> > Can you pass the parent PID on a (Windows-only) command-line directive
> > when you spawn the children? The PID would then be stored into a handy
> > global somewhere, for reference during the restart.
> There are two cases to consider. The first is when the child wants to
> initiate a restart. In this case, the parent passes its pid to the child via
> an evnvironemt variable (AP_PARENT_PID), so this case if covered. The second
> case is when the admin wants to initiate a restart with 'apache -k restart'.

Ah! I see (now) how that second case is different. And how it complicates
the problem :-)

> To handle the second case, we need to stash the parent pid in some
> 'findable' location, like in a file (or maybe the registry?). The location
> of the file with the parent pid is specified by the PidFile directive in
> httpd.conf.

I would think the registry would be the more reliable location (as you
originally mentioned: there could be problems locating the PidFile (also
think about how <IfDefine...> complicates things(!))). Placing the PID
into the registry would have possible issues when you run more than one
apache process (although I think that may be a problem, in any case, with
the -k restart option).

Hrm. If you can establish a naming scheme for each running Apache process,
then maybe you could use a named mutex to signal shutdown. Are you using
WaitForObjects (and therefore able to wait on a mutex)? apache -k restart
would simply signal the named mutex.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/


Re: cvs commit: apache-2.0/src/os/win32 main_win32.c

Posted by Bill Stoddard <st...@raleigh.ibm.com>.
> Can you pass the parent PID on a (Windows-only) command-line directive
> when you spawn the children? The PID would then be stored into a handy
> global somewhere, for reference during the restart.
There are two cases to consider. The first is when the child wants to
initiate a restart. In this case, the parent passes its pid to the child via
an evnvironemt variable (AP_PARENT_PID), so this case if covered. The second
case is when the admin wants to initiate a restart with 'apache -k restart'.
To handle the second case, we need to stash the parent pid in some
'findable' location, like in a file (or maybe the registry?). The location
of the file with the parent pid is specified by the PidFile directive in
httpd.conf.

Bill



Re: cvs commit: apache-2.0/src/os/win32 main_win32.c

Posted by Greg Stein <gs...@lyra.org>.
On 14 Feb 2000 stoddard@hyperreal.org wrote:
> stoddard    00/02/14 14:01:11
> 
>   Modified:    src/main http_main.c
>                src/modules/mpm/winnt winnt.c
>                src/os/win32 main_win32.c
>   Log:
>   Rework the code to handle apache -k shutdown|restart. The fundamental problem
>   being solved here is determining the best way to discover the Apache
>   parent process PID (stored in the location specified by the PidFile directive).
>   This patch attempts to read the config file directly to determine the
>   pidfile and avoids going through the motions of calling all the module initialization
>   routines.
>   
>   This patch will not work if the pidfile directive is in a file pointed to by
>   an include directive. Not sure is this is a common case or not on Windows.
>   If it is, it is easy enough to add a bit more code to follow include
>   directives. An interesting modification would be to detect the presence of a \
>   -C directive containing a pointer to the pidfile: E.g.,
>   apache -k restart -C "pidfile d:/mypidfile". Let's keep it simple for now and
>   see what happens.

Can you pass the parent PID on a (Windows-only) command-line directive
when you spawn the children? The PID would then be stored into a handy
global somewhere, for reference during the restart.

(and on Unix, this global would simply be filled pre-fork)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/