1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-05 16:55:50 +03:00

* Move the Example modules to the newly created examples subdirectory

* Hopefully correctly fudge the NWGNU make files
* Add mod_example_ipc (without NWGNU stuff or dsp)


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@596093 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sander Temme
2007-11-18 15:41:03 +00:00
parent f9aa316d03
commit df96b77cf2
16 changed files with 678 additions and 27 deletions

View File

@@ -18,6 +18,10 @@ dav/
echo/ echo/
examples/
This directory contains some sample code that should help you on your
way to develop your own Apache modules.
experimental/ experimental/
In this directory we've placed some modules which we think In this directory we've placed some modules which we think
provide some pretty interesting functionality, but which provide some pretty interesting functionality, but which

View File

@@ -0,0 +1,3 @@
# a modules Makefile has no explicit targets -- they will be defined by
# whatever modules are enabled. just grab special.mk to deal with this.
include $(top_srcdir)/build/special.mk

View File

@@ -102,19 +102,19 @@ endif
# This is used by the link 'name' directive to name the nlm. If left blank # This is used by the link 'name' directive to name the nlm. If left blank
# TARGET_nlm (see below) will be used. # TARGET_nlm (see below) will be used.
# #
NLM_NAME = example NLM_NAME = example_hooks
# #
# This is used by the link '-desc ' directive. # This is used by the link '-desc ' directive.
# If left blank, NLM_NAME will be used. # If left blank, NLM_NAME will be used.
# #
NLM_DESCRIPTION = Apache $(VERSION_STR) Example Module NLM_DESCRIPTION = Apache $(VERSION_STR) Example Hook Callback Handler Module
# #
# This is used by the '-threadname' directive. If left blank, # This is used by the '-threadname' directive. If left blank,
# NLM_NAME Thread will be used. # NLM_NAME Thread will be used.
# #
NLM_THREAD_NAME = Example Module NLM_THREAD_NAME = Example Hook Callback Handler Module
# #
# If this is specified, it will override VERSION value in # If this is specified, it will override VERSION value in
@@ -159,7 +159,7 @@ XDCDATA =
# If there is an NLM target, put it here # If there is an NLM target, put it here
# #
TARGET_nlm = \ TARGET_nlm = \
$(OBJDIR)/example.nlm \ $(OBJDIR)/example_hooks.nlm \
$(EOLIST) $(EOLIST)
# #
@@ -173,7 +173,7 @@ TARGET_lib = \
# Paths must all use the '/' character # Paths must all use the '/' character
# #
FILES_nlm_objs = \ FILES_nlm_objs = \
$(OBJDIR)/mod_example.o \ $(OBJDIR)/mod_example_hooks.o \
$(EOLIST) $(EOLIST)
# #

View File

@@ -0,0 +1,255 @@
#
# Declare the sub-directories to be built here
#
SUBDIRS = \
$(EOLIST)
#
# Get the 'head' of the build environment. This includes default targets and
# paths to tools
#
include $(AP_WORK)\build\NWGNUhead.inc
#
# build this level's files
#
# Make sure all needed macro's are defined
#
#
# These directories will be at the beginning of the include list, followed by
# INCDIRS
#
XINCDIRS += \
$(EOLIST)
#
# These flags will come after CFLAGS
#
XCFLAGS += \
$(EOLIST)
#
# These defines will come after DEFINES
#
XDEFINES += \
$(EOLIST)
#
# These flags will be added to the link.opt file
#
XLFLAGS += \
$(EOLIST)
#
# These values will be appended to the correct variables based on the value of
# RELEASE
#
ifeq "$(RELEASE)" "debug"
XINCDIRS += \
$(EOLIST)
XCFLAGS += \
$(EOLIST)
XDEFINES += \
$(EOLIST)
XLFLAGS += \
$(EOLIST)
endif
ifeq "$(RELEASE)" "noopt"
XINCDIRS += \
$(EOLIST)
XCFLAGS += \
$(EOLIST)
XDEFINES += \
$(EOLIST)
XLFLAGS += \
$(EOLIST)
endif
ifeq "$(RELEASE)" "release"
XINCDIRS += \
$(EOLIST)
XCFLAGS += \
$(EOLIST)
XDEFINES += \
$(EOLIST)
XLFLAGS += \
$(EOLIST)
endif
#
# These are used by the link target if an NLM is being generated
# This is used by the link 'name' directive to name the nlm. If left blank
# TARGET_nlm (see below) will be used.
#
NLM_NAME =
#
# This is used by the link '-desc ' directive.
# If left blank, NLM_NAME will be used.
#
NLM_DESCRIPTION =
#
# This is used by the '-threadname' directive. If left blank,
# NLM_NAME Thread will be used.
#
NLM_THREAD_NAME =
#
# If this is specified, it will override VERSION value in
# $(AP_WORK)\build\NWGNUenvironment.inc
#
NLM_VERSION =
#
# If this is specified, it will override the default of 64K
#
NLM_STACK_SIZE =
#
# If this is specified it will be used by the link '-entry' directive
#
NLM_ENTRY_SYM =
#
# If this is specified it will be used by the link '-exit' directive
#
NLM_EXIT_SYM =
#
# If this is specified it will be used by the link '-check' directive
#
NLM_CHECK_SYM =
#
# If these are specified it will be used by the link '-flags' directive
#
NLM_FLAGS =
#
# If this is specified it will be linked in with the XDCData option in the def
# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
# by setting APACHE_UNIPROC in the environment
#
XDCDATA =
#
# If there is an NLM target, put it here
#
# We are referencing example.nlm twice to get around a known issue with the
# makefiles. Normally if there is only one element to be built within a
# directory, the makefile for the single element would be called NWGNUmakefile.
# But if there are multiples, the parent NWGNUmakefile must reference more
# than one submakefile. Because the experimental directory might vary in the
# number of submakefiles, but for the moment only contains one, we reference
# it twice to allow it parent NWGNUmakefile to work properly. If another
# submakefile is added, the extra reference to example.nlm should be removed.
TARGET_nlm = \
$(OBJDIR)/example.nlm \
$(OBJDIR)/case_flt.nlm \
$(OBJDIR)/case_flt_in.nlm \
$(EOLIST)
#
# If there is an LIB target, put it here
#
TARGET_lib = \
$(EOLIST)
#
# These are the OBJ files needed to create the NLM target above.
# Paths must all use the '/' character
#
FILES_nlm_objs = \
$(EOLIST)
#
# These are the LIB files needed to create the NLM target above.
# These will be added as a library command in the link.opt file.
#
FILES_nlm_libs = \
$(EOLIST)
#
# These are the modules that the above NLM target depends on to load.
# These will be added as a module command in the link.opt file.
#
FILES_nlm_modules = \
$(EOLIST)
#
# If the nlm has a msg file, put it's path here
#
FILE_nlm_msg =
#
# If the nlm has a hlp file put it's path here
#
FILE_nlm_hlp =
#
# If this is specified, it will override $(NWOS)\copyright.txt.
#
FILE_nlm_copyright =
#
# Any additional imports go here
#
FILES_nlm_Ximports = \
$(EOLIST)
#
# Any symbols exported to here
#
FILES_nlm_exports = \
$(EOLIST)
#
# These are the OBJ files needed to create the LIB target above.
# Paths must all use the '/' character
#
FILES_lib_objs = \
$(EOLIST)
#
# implement targets and dependancies (leave this section alone)
#
libs :: $(OBJDIR) $(TARGET_lib)
nlms :: libs $(TARGET_nlm)
#
# Updated this target to create necessary directories and copy files to the
# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
#
install :: nlms FORCE
copy $(OBJDIR)\*.nlm $(INSTALL)\$(BASEDIR)\modules\*.*
#
# Any specialized rules here
#
#
# Include the 'tail' makefile that has targets that depend on variables defined
# in this makefile
#
include $(AP_WORK)\build\NWGNUtail.inc

View File

@@ -0,0 +1,9 @@
APACHE_MODPATH_INIT(examples)
APACHE_MODULE(example_hooks, Example hook callback handler module, , , no)
APACHE_MODULE(case_filter, Example uppercase conversion filter, , , no)
APACHE_MODULE(case_filter_in, Example uppercase conversion input filter, , , no)
APACHE_MODULE(example_ipc, Example of shared memory and mutex usage, , , no)
APACHE_MODPATH_FINISH

View File

@@ -25,16 +25,17 @@
* this module, but which may have counterparts in *real* modules, are * this module, but which may have counterparts in *real* modules, are
* prefixed with 'x_' instead of 'example_'. * prefixed with 'x_' instead of 'example_'.
* *
* To use mod_example, configure the Apache build with --enable-example and * To use mod_example_hooks, configure the Apache build with
* compile. Set up a <Location> block in your configuration file like so: * --enable-example and compile. Set up a <Location> block in your
* configuration file like so:
* *
* <Location /example> * <Location /example>
* SetHandler example-handler * SetHandler example-hooks-handler
* </Location> * </Location>
* *
* When you look at that location on your server, you will see a backtrace of * When you look at that location on your server, you will see a backtrace of
* the callbacks that have been invoked up to that point. See the ErrorLog for * the callbacks that have been invoked up to that point. See the ErrorLog for
* more information on code paths that touch mod_example. * more information on code paths that touch mod_example_hooks.
* *
* IMPORTANT NOTES * IMPORTANT NOTES
* =============== * ===============
@@ -44,7 +45,7 @@
* request processing, and produces copious amounts of logging data. This will * request processing, and produces copious amounts of logging data. This will
* negatively affect server performance. * negatively affect server performance.
* *
* Do NOT use mod_example as the basis for your own code. This module * Do NOT use mod_example_hooks as the basis for your own code. This module
* implements every callback hook offered by the Apache core, and your * implements every callback hook offered by the Apache core, and your
* module will almost certainly not have to implement this much. If you * module will almost certainly not have to implement this much. If you
* want a simple module skeleton to start development, use apxs -g. * want a simple module skeleton to start development, use apxs -g.
@@ -128,7 +129,7 @@ static const char *trace = NULL;
* Declare ourselves so the configuration routines can find and know us. * Declare ourselves so the configuration routines can find and know us.
* We'll fill it in at the end of the module. * We'll fill it in at the end of the module.
*/ */
module AP_MODULE_DECLARE_DATA example_module; module AP_MODULE_DECLARE_DATA example_hooks_module;
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* */ /* */
@@ -279,7 +280,7 @@ module AP_MODULE_DECLARE_DATA example_module;
*/ */
static x_cfg *our_dconfig(const request_rec *r) static x_cfg *our_dconfig(const request_rec *r)
{ {
return (x_cfg *) ap_get_module_config(r->per_dir_config, &example_module); return (x_cfg *) ap_get_module_config(r->per_dir_config, &example_hooks_module);
} }
/* /*
@@ -293,7 +294,7 @@ static x_cfg *our_dconfig(const request_rec *r)
*/ */
static x_cfg *our_sconfig(const server_rec *s) static x_cfg *our_sconfig(const server_rec *s)
{ {
return (x_cfg *) ap_get_module_config(s->module_config, &example_module); return (x_cfg *) ap_get_module_config(s->module_config, &example_hooks_module);
} }
/* /*
@@ -301,7 +302,7 @@ static x_cfg *our_sconfig(const server_rec *s)
*/ */
static x_cfg *our_rconfig(const request_rec *r) static x_cfg *our_rconfig(const request_rec *r)
{ {
return (x_cfg *) ap_get_module_config(r->request_config, &example_module); return (x_cfg *) ap_get_module_config(r->request_config, &example_hooks_module);
} }
#endif /* if 0 */ #endif /* if 0 */
@@ -310,7 +311,7 @@ static x_cfg *our_rconfig(const request_rec *r)
*/ */
static x_cfg *our_cconfig(const conn_rec *c) static x_cfg *our_cconfig(const conn_rec *c)
{ {
return (x_cfg *) ap_get_module_config(c->conn_config, &example_module); return (x_cfg *) ap_get_module_config(c->conn_config, &example_hooks_module);
} }
/* /*
@@ -386,7 +387,7 @@ static void trace_startup(apr_pool_t *p, server_rec *s, x_cfg *mconfig,
* This utility route traces the hooks called as a request is handled. * This utility route traces the hooks called as a request is handled.
* It takes the current request as argument * It takes the current request as argument
*/ */
#define TRACE_NOTE "example-trace" #define TRACE_NOTE "example-hooks-trace"
static void trace_request(const request_rec *r, const char *note) static void trace_request(const request_rec *r, const char *note)
{ {
@@ -432,7 +433,7 @@ static void trace_request(const request_rec *r, const char *note)
* the connection and its pool to itself entirely, and in * the connection and its pool to itself entirely, and in
* multi-threaded mode each connection will have its own pool. * multi-threaded mode each connection will have its own pool.
*/ */
#define CONN_NOTE "example-connection" #define CONN_NOTE "example-hooks-connection"
static void trace_connection(conn_rec *c, const char *note) static void trace_connection(conn_rec *c, const char *note)
{ {
@@ -983,7 +984,7 @@ static int x_handler(request_rec *r)
trace_request(r, note); trace_request(r, note);
/* If it's not for us, get out as soon as possible. */ /* If it's not for us, get out as soon as possible. */
if (strcmp(r->handler, "example-handler")) { if (strcmp(r->handler, "example-hooks-handler")) {
return DECLINED; return DECLINED;
} }
@@ -1007,11 +1008,11 @@ static int x_handler(request_rec *r)
ap_rputs(DOCTYPE_HTML_3_2, r); ap_rputs(DOCTYPE_HTML_3_2, r);
ap_rputs("<HTML>\n", r); ap_rputs("<HTML>\n", r);
ap_rputs(" <HEAD>\n", r); ap_rputs(" <HEAD>\n", r);
ap_rputs(" <TITLE>mod_example Module Content-Handler Output\n", r); ap_rputs(" <TITLE>mod_example_hooks Module Content-Handler Output\n", r);
ap_rputs(" </TITLE>\n", r); ap_rputs(" </TITLE>\n", r);
ap_rputs(" </HEAD>\n", r); ap_rputs(" </HEAD>\n", r);
ap_rputs(" <BODY>\n", r); ap_rputs(" <BODY>\n", r);
ap_rputs(" <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r); ap_rputs(" <H1><SAMP>mod_example_hooks</SAMP> Module Content-Handler Output\n", r);
ap_rputs(" </H1>\n", r); ap_rputs(" </H1>\n", r);
ap_rputs(" <P>\n", r); ap_rputs(" <P>\n", r);
ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n", ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n",
@@ -1505,7 +1506,7 @@ static const command_rec x_cmds[] =
* Module definition for configuration. If a particular callback is not * Module definition for configuration. If a particular callback is not
* needed, replace its routine name below with the word NULL. * needed, replace its routine name below with the word NULL.
*/ */
module AP_MODULE_DECLARE_DATA example_module = module AP_MODULE_DECLARE_DATA example_hooks_module =
{ {
STANDARD20_MODULE_STUFF, STANDARD20_MODULE_STUFF,
x_create_dir_config, /* per-directory config creator */ x_create_dir_config, /* per-directory config creator */

View File

@@ -0,0 +1,385 @@
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* mod_example_ipc -- Apache sample module
*
* This module illustrates the use in an Apache 2.x module of the Interprocess
* Communications routines that come with APR. It is example code, and not meant
* to be used in a production server.
*
* To play with this sample module first compile it into a DSO file and install
* it into Apache's modules directory by running:
*
* $ /path/to/apache2/bin/apxs -c -i mod_example_ipc.c
*
* Then activate it in Apache's httpd.conf file for instance for the URL
* /example_ipc in as follows:
*
* # httpd.conf
* LoadModule example_ipc_module modules/mod_example_ipc.so
* <Location /example_ipc>
* SetHandler example_ipc
* </Location>
*
* Then restart Apache via
*
* $ /path/to/apache2/bin/apachectl restart
*
* The module allocates a counter in shared memory, which is incremented by the
* request handler under a mutex. After installation, activate the handler by
* hitting the URL configured above with ab at various concurrency levels to see
* how mutex contention affects server performance.
*/
#include "apr.h"
#include "apr_strings.h"
#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "ap_config.h"
#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
#include "unixd.h"
#define MOD_EXIPC_SET_MUTEX_PERMS /* XXX Apache should define something */
#endif
#if APR_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if APR_HAVE_UNISTD_H
#include <unistd.h>
#endif
#define HTML_HEADER "<html>\n<head>\n<title>Mod_example_IPC Status Page " \
"</title>\n</head>\n<body>\n<h1>Mod_example_IPC Status</h1>\n"
#define HTML_FOOTER "</body>\n</html>\n"
/* Number of microseconds to camp out on the mutex */
#define CAMPOUT 10
/* Maximum number of times we camp out before giving up */
#define MAXCAMP 10
/* Number of microseconds the handler sits on the lock once acquired. */
#define SLEEPYTIME 1000
apr_shm_t *exipc_shm; /* Pointer to shared memory block */
char *shmfilename; /* Shared memory file name, used on some systems */
apr_global_mutex_t *exipc_mutex; /* Lock around shared memory segment access */
char *mutexfilename; /* Lock file name, used on some systems */
/* Data structure for shared memory block */
typedef struct exipc_data {
apr_uint64_t counter;
/* More fields if necessary */
} exipc_data;
/*
* Clean up the shared memory block. This function is registered as
* cleanup function for the configuration pool, which gets called
* on restarts. It assures that the new children will not talk to a stale
* shared memory segment.
*/
static apr_status_t shm_cleanup_wrapper(void *unused) {
if (exipc_shm)
return apr_shm_destroy(exipc_shm);
return OK;
}
/*
* This routine is called in the parent, so we'll set up the shared
* memory segment and mutex here.
*/
static int exipc_post_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptemp, server_rec *s)
{
void *data; /* These two help ensure that we only init once. */
const char *userdata_key;
apr_status_t rs;
exipc_data *base;
const char *tempdir;
/*
* The following checks if this routine has been called before.
* This is necessary because the parent process gets initialized
* a couple of times as the server starts up, and we don't want
* to create any more mutexes and shared memory segments than
* we're actually going to use.
*
* The key needs to be unique for the entire web server, so put
* the module name in it.
*/
userdata_key = "example_ipc_init_module";
apr_pool_userdata_get(&data, userdata_key, s->process->pool);
if (!data) {
/*
* If no data was found for our key, this must be the first
* time the module is initialized. Put some data under that
* key and return.
*/
apr_pool_userdata_set((const void *) 1, userdata_key,
apr_pool_cleanup_null, s->process->pool);
return OK;
} /* Kilroy was here */
/*
* Both the shared memory and mutex allocation routines take a
* file name. Depending on system-specific implementation of these
* routines, that file may or may not actually be created. We'd
* like to store those files in the operating system's designated
* temporary directory, which APR can point us to.
*/
rs = apr_temp_dir_get(&tempdir, pconf);
if (APR_SUCCESS != rs) {
ap_log_error(APLOG_MARK, APLOG_ERR, rs, s,
"Failed to find temporary directory");
return HTTP_INTERNAL_SERVER_ERROR;
}
/* Create the shared memory segment */
/*
* Create a unique filename using our pid. This information is
* stashed in the global variable so the children inherit it.
*/
shmfilename = apr_psprintf(pconf, "%s/httpd_shm.%ld", tempdir,
(long int)getpid());
/* Now create that segment */
rs = apr_shm_create(&exipc_shm, sizeof(exipc_data),
(const char *) shmfilename, pconf);
if (APR_SUCCESS != rs) {
ap_log_error(APLOG_MARK, APLOG_ERR, rs, s,
"Failed to create shared memory segment on file %s",
shmfilename);
return HTTP_INTERNAL_SERVER_ERROR;
}
/* Created it, now let's zero it out */
base = (exipc_data *)apr_shm_baseaddr_get(exipc_shm);
base->counter = 0;
/* Create global mutex */
/*
* Create another unique filename to lock upon. Note that
* depending on OS and locking mechanism of choice, the file
* may or may not be actually created.
*/
mutexfilename = apr_psprintf(pconf, "%s/httpd_mutex.%ld", tempdir,
(long int) getpid());
rs = apr_global_mutex_create(&exipc_mutex, (const char *) mutexfilename,
APR_LOCK_DEFAULT, pconf);
if (APR_SUCCESS != rs) {
ap_log_error(APLOG_MARK, APLOG_ERR, rs, s,
"Failed to create mutex on file %s",
mutexfilename);
return HTTP_INTERNAL_SERVER_ERROR;
}
/*
* After the mutex is created, its permissions need to be adjusted
* on unix platforms so that the child processe can acquire
* it. This call takes care of that. The preprocessor define was
* set up early in this source file since Apache doesn't provide
* it.
*/
#ifdef MOD_EXIPC_SET_MUTEX_PERMS
rs = unixd_set_global_mutex_perms(exipc_mutex);
if (APR_SUCCESS != rs) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rs, s,
"Parent could not set permissions on Example IPC "
"mutex: check User and Group directives");
return HTTP_INTERNAL_SERVER_ERROR;
}
#endif /* MOD_EXIPC_SET_MUTEX_PERMS */
/*
* Destroy the shm segment when the configuration pool gets destroyed. This
* happens on server restarts. The parent will then (above) allocate a new
* shm segment that the new children will bind to.
*/
apr_pool_cleanup_register(pconf, NULL, shm_cleanup_wrapper,
apr_pool_cleanup_null);
return OK;
}
/*
* This routine gets called when a child inits. We use it to attach
* to the shared memory segment, and reinitialize the mutex.
*/
static void exipc_child_init(apr_pool_t *p, server_rec *s)
{
apr_status_t rs;
/*
* Re-open the mutex for the child. Note we're reusing
* the mutex pointer global here.
*/
rs = apr_global_mutex_child_init(&exipc_mutex,
(const char *) mutexfilename,
p);
if (APR_SUCCESS != rs) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rs, s,
"Failed to reopen mutex on file %s",
shmfilename);
/* There's really nothing else we can do here, since This
* routine doesn't return a status. If this ever goes wrong,
* it will turn Apache into a fork bomb. Let's hope it never
* will.
*/
exit(1); /* Ugly, but what else? */
}
}
/* The sample content handler */
static int exipc_handler(request_rec *r)
{
int gotlock = 0;
int camped;
apr_time_t startcamp;
apr_int64_t timecamped;
apr_status_t rs;
exipc_data *base;
if (strcmp(r->handler, "example_ipc")) {
return DECLINED;
}
/*
* The main function of the handler, aside from sending the
* status page to the client, is to increment the counter in
* the shared memory segment. This action needs to be mutexed
* out using the global mutex.
*/
/*
* First, acquire the lock. This code is a lot more involved than
* it usually needs to be, because the process based trylock
* routine is not implemented on unix platforms. I left it in to
* show how it would work if trylock worked, and for situations
* and platforms where trylock works.
*/
for (camped = 0, timecamped = 0; camped < MAXCAMP; camped++) {
rs = apr_global_mutex_trylock(exipc_mutex);
if (APR_STATUS_IS_EBUSY(rs)) {
apr_sleep(CAMPOUT);
} else if (APR_SUCCESS == rs) {
gotlock = 1;
break; /* Get out of the loop */
} else if (APR_STATUS_IS_ENOTIMPL(rs)) {
/* If it's not implemented, just hang in the mutex. */
startcamp = apr_time_now();
rs = apr_global_mutex_lock(exipc_mutex);
timecamped = (apr_int64_t) (apr_time_now() - startcamp);
if (APR_SUCCESS == rs) {
gotlock = 1;
break; /* Out of the loop */
} else {
/* Some error, log and bail */
ap_log_error(APLOG_MARK, APLOG_ERR, rs, r->server,
"Child %ld failed to acquire lock",
(long int)getpid());
break; /* Out of the loop without having the lock */
}
} else {
/* Some other error, log and bail */
ap_log_error(APLOG_MARK, APLOG_ERR, rs, r->server,
"Child %ld failed to try and acquire lock",
(long int)getpid());
break; /* Out of the loop without having the lock */
}
/*
* The only way to get to this point is if the trylock worked
* and returned BUSY. So, bump the time and try again
*/
timecamped += CAMPOUT;
ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_NOTICE,
0, r->server, "Child %ld camping out on mutex for %d "
"microseconds",
(long int) getpid(), timecamped);
} /* Lock acquisition loop */
/* Sleep for a millisecond to make it a little harder for
* httpd children to acquire the lock.
*/
apr_sleep(SLEEPYTIME);
r->content_type = "text/html";
if (!r->header_only) {
ap_rputs(HTML_HEADER, r);
if (gotlock) {
/* Increment the counter */
base = (exipc_data *)apr_shm_baseaddr_get(exipc_shm);
base->counter++;
/* Send a page with our pid and the new value of the counter. */
ap_rprintf(r, "<p>Lock acquired after %ld microseoncds.</p>\n",
(long int) timecamped);
ap_rputs("<table border=\"1\">\n", r);
ap_rprintf(r, "<tr><td>Child pid:</td><td>%d</td></tr>\n",
(int) getpid());
ap_rprintf(r, "<tr><td>Counter:</td><td>%u</td></tr>\n",
(unsigned int)base->counter);
ap_rputs("</table>\n", r);
} else {
/*
* Send a page saying that we couldn't get the lock. Don't say
* what the counter is, because without the lock the value could
* race.
*/
ap_rprintf(r, "<p>Child %d failed to acquire lock "
"after camping out for %d microseconds.</p>\n",
(int) getpid(), (int) timecamped);
}
ap_rputs(HTML_FOOTER, r);
} /* r->header_only */
/* Release the lock */
if (gotlock)
rs = apr_global_mutex_unlock(exipc_mutex);
/* Swallowing the result because what are we going to do with it at
* this stage?
*/
return OK;
}
static void exipc_register_hooks(apr_pool_t *p)
{
ap_hook_post_config(exipc_post_config, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_child_init(exipc_child_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(exipc_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA example_ipc_module = {
STANDARD20_MODULE_STUFF,
NULL, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
NULL, /* create per-server config structures */
NULL, /* merge per-server config structures */
NULL, /* table of config file commands */
exipc_register_hooks /* register hooks */
};

View File

@@ -160,9 +160,6 @@ XDCDATA =
# it twice to allow it parent NWGNUmakefile to work properly. If another # it twice to allow it parent NWGNUmakefile to work properly. If another
# submakefile is added, the extra reference to example.nlm should be removed. # submakefile is added, the extra reference to example.nlm should be removed.
TARGET_nlm = \ TARGET_nlm = \
$(OBJDIR)/example.nlm \
$(OBJDIR)/case_flt.nlm \
$(OBJDIR)/case_flt_in.nlm \
$(OBJDIR)/substitute.nlm \ $(OBJDIR)/substitute.nlm \
$(EOLIST) $(EOLIST)

View File

@@ -1,9 +1,6 @@
APACHE_MODPATH_INIT(experimental) APACHE_MODPATH_INIT(experimental)
APACHE_MODULE(example, example and demo module, , , no)
APACHE_MODULE(case_filter, example uppercase conversion filter, , , no)
APACHE_MODULE(case_filter_in, example uppercase conversion input filter, , , no)
APACHE_MODULE(substitute, response content rewrite-like filtering, , , most) APACHE_MODULE(substitute, response content rewrite-like filtering, , , most)
APACHE_MODPATH_FINISH APACHE_MODPATH_FINISH