From: Jim Jagielski Date: Tue, 4 Sep 2001 18:15:16 +0000 (+0000) Subject: Add the AcceptMutex runtime directive, which allows for the X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0940525e855fe1f26177ab5664f76bd41184b6ec;p=thirdparty%2Fapache%2Fhttpd.git Add the AcceptMutex runtime directive, which allows for the accept mutexing method to be set at runtime (the suite of methods is set at compile time still). PR: Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@90892 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/CHANGES b/src/CHANGES index 8f2db5df690..af7967c5a20 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -1,5 +1,15 @@ Changes with Apache 1.3.21 + *) Addition of the AcceptMutex runtime directive. The accept mutex + method is now runtime controllable. The suite of available methods + per platform is defined at compile time (with HAVE_FOO_SERIALIZED_ACCEPT + noting that the method is available and works, and + USE_FOO_SERIALIZED_ACCEPT noting that it should be the default + method in absense of any AcceptMutex line, or via AcceptMutex default) + and selectable at runtime. The full (current) suite is uslock, + pthread, sysvsem, fcntl, flock, os2sem, tpfcore and none, but + not all platforms accept all methods. [Jim Jagielski] + *) Parallel to a change in Apache-2.0, the manual directory was moved out of the DocumentRoot tree to simplify the separation of private content&configuration from server's on-line diff --git a/src/PORTING b/src/PORTING index 52103d24f1d..daabd772269 100644 --- a/src/PORTING +++ b/src/PORTING @@ -244,13 +244,20 @@ build for your OS. USE_MMAP_FILES: Enable the use of mmap() for sending static files. If HAVE_MMAP is not #defined, this will automatically be unset. +-- USE_*_SERIALIZED_ACCEPT: See htdocs/manual/misc/perf-tuning.html for an in-depth discussion of - why these are required. These are choices for implementing a semaphore - between children entering accept(). A complete port should define one - of these, many may work and it's worthwhile timing them. Without these - the server will not implement multiple Listen directives reliably. + why these are required. These are choices for implementing a mutex + between children entering accept(). A complete port should define at + least one of these, many may work and it's worthwhile timing them. + Without these the server will not implement multiple Listen directives + reliably. Please note that as of 1.3.21, we can set the method at runtime. + To so do, we specify which methods are available at compile time + with the HAVE_FOO_SERIALIZED_ACCEPT #defines. The USE_FOO_SERIALIZED_ACCEPT + is used to pick the default version of all those available. These are + set at compile time usually in include/ap_config.h but can also be + done at the compile command line. USE_FCNTL_SERIALIZED_ACCEPT: Use fcntl() to implement the semaphore. diff --git a/src/include/ap_config.h b/src/include/ap_config.h index 5571addcfde..0c77f2d94dd 100644 --- a/src/include/ap_config.h +++ b/src/include/ap_config.h @@ -118,7 +118,7 @@ stat() properly */ typedef int rlim_t; #define JMP_BUF sigjmp_buf #define NO_LONG_DOUBLE -#define USE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FLOCK_SERIALIZED_ACCEPT #define _BSD_SOURCE #define EAGAIN EWOULDBLOCK int initgroups (char *, int); @@ -154,7 +154,7 @@ extern char *inet_ntoa(); #define S_IREAD S_IRUSR #define S_IWRITE S_IWUSR #define PF_INET AF_INET -#define USE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #elif defined(SUNOS4) #define HAVE_GMTOFF 1 @@ -170,7 +170,7 @@ char *mktemp(char *); typedef int rlim_t; #define memmove(a,b,c) bcopy(b,a,c) #define NO_LINGCLOSE -#define USE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FLOCK_SERIALIZED_ACCEPT #define NEED_DIFFTIME #define HAVE_SYSLOG 1 @@ -179,6 +179,8 @@ typedef int rlim_t; #define NO_KILLPG #undef NO_SETSID #define bzero(a,b) memset(a,0,b) +#define HAVE_SYSVSEM_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #if !defined(USE_SYSVSEM_SERIALIZED_ACCEPT) && \ !defined(USE_PTHREAD_SERIALIZED_ACCEPT) #define USE_FCNTL_SERIALIZED_ACCEPT @@ -197,6 +199,10 @@ int gethostname(char *name, int namelen); * there's some weird conflict with non-BSD signals */ #define NO_KILLPG #undef NO_SETSID +#define HAVE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_USLOCK_SERIALIZED_ACCEPT +#define HAVE_SYSVSEM_SERIALIZED_ACCEPT #if !defined(USE_FLOCK_SERIALIZED_ACCEPT) && \ !defined(USE_USLOCK_SERIALIZED_ACCEPT) && \ !defined(USE_SYSVSEM_SERIALIZED_ACCEPT) @@ -226,7 +232,7 @@ int gethostname(char *name, int namelen); #undef HAVE_GMTOFF #define NO_KILLPG #undef NO_SETSID -#define USE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #ifndef _HPUX_SOURCE #define _HPUX_SOURCE #endif @@ -245,12 +251,12 @@ typedef int rlim_t; #define HAVE_SHMGET #define USE_SHMGET_SCOREBOARD #undef HAVE_GMTOFF -#define USE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT /* feeling brave? want to try using POSIX mutexes? */ /* #define HAVE_MMAP */ /* #define USE_MMAP_SCOREBOARD */ /* #define USE_MMAP_FILES */ -/* #define USE_PTHREAD_SERIALIZED_ACCEPT */ +/* #define HAVE_PTHREAD_SERIALIZED_ACCEPT */ #define NO_KILLPG #undef NO_SETSID #define HAVE_SYSLOG @@ -274,6 +280,7 @@ typedef int rlim_t; #ifdef NEED_RLIM_T typedef int rlim_t; #endif +#define HAVE_FCNTL_SERIALIZED_ACCEPT #if !defined(USE_PTHREAD_SERIALIZED_ACCEPT) #define USE_FCNTL_SERIALIZED_ACCEPT #endif @@ -307,7 +314,7 @@ typedef int rlim_t; #define USE_MMAP_FILES #define NO_LONG_DOUBLE #define HAVE_SYSLOG 1 -#define USE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FLOCK_SERIALIZED_ACCEPT #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT #elif defined(PARAGON) @@ -329,7 +336,7 @@ typedef int rlim_t; #define HAVE_SYSLOG 1 #define USE_MMAP_FILES 1 #define USE_MMAP_SCOREBOARD 1 -#define USE_FCNTL_SERIALIZED_ACCEPT 1 +#define HAVE_FCNTL_SERIALIZED_ACCEPT 1 #define JMP_BUF sigjmp_buf #undef NO_SETSID #if SEQUENT < 40 @@ -432,6 +439,8 @@ typedef int pid_t; #define HAVE_SNPRINTF #define JMP_BUF jmp_buf #define USE_LONGJMP +#define HAVE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #define USE_FLOCK_SERIALIZED_ACCEPT #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT @@ -475,7 +484,8 @@ typedef int pid_t; * in new-httpd archives for performance numbers indicating these * are the right choices for linux 2.2.x and later */ -#define USE_SYSVSEM_SERIALIZED_ACCEPT +#define HAVE_SYSVSEM_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT #include #if _SEM_SEMUN_UNDEFINED @@ -515,7 +525,7 @@ typedef int rlim_t; #elif defined(SCO5) -#define USE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #define HAVE_MMAP 1 #define USE_MMAP_SCOREBOARD #define USE_MMAP_FILES @@ -547,7 +557,7 @@ extern char *crypt(); #undef NO_SETSID #define NEED_STRDUP /* fcntl() locking is expensive with NFS */ -#define USE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FLOCK_SERIALIZED_ACCEPT #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT #define HAVE_SHMGET 1 #define USE_SHMGET_SCOREBOARD @@ -576,6 +586,7 @@ extern char *crypt(); #endif /* MPRAS */ #define bzero(a,b) memset(a,0,b) /* A lot of SVR4 systems need this */ +#define HAVE_FCNTL_SERIALIZED_ACCEPT #ifndef USE_SYSVSEM_SERIALIZED_ACCEPT #define USE_FCNTL_SERIALIZED_ACCEPT #endif @@ -593,7 +604,7 @@ extern char *crypt(); #elif defined(UW) #if UW < 700 -#define USE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #define NO_LINGCLOSE #define NO_KILLPG #endif @@ -627,7 +638,7 @@ extern char *crypt(); #endif #define bzero(a,b) memset(a,0,b) /* A lot of SVR4 systems need this */ -#define USE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #define ap_inet_addr inet_network #define HAVE_SYSLOG 1 @@ -646,7 +657,7 @@ extern char *crypt(); #define HAVE_MMAP 1 #define USE_MMAP_SCOREBOARD #define USE_MMAP_FILES -#define USE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FLOCK_SERIALIZED_ACCEPT #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT #elif defined(UTS21) @@ -700,7 +711,7 @@ extern char *crypt(); (defined(__FreeBSD_version) && (__FreeBSD_version < 220000)) typedef quad_t rlim_t; #endif -#define USE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FLOCK_SERIALIZED_ACCEPT #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT #define HAVE_SYSLOG 1 #define SYS_SIGLIST sys_siglist @@ -726,7 +737,7 @@ int initgroups(char *, int); #include #define HAVE_MMAP 1 #define USE_POSIX_SCOREBOARD -#define USE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FLOCK_SERIALIZED_ACCEPT #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT #define HAVE_SYSLOG 1 @@ -734,8 +745,9 @@ int initgroups(char *, int); #undef HAVE_GMTOFF #undef USE_MMAP_SCOREBOARD #undef USE_SHMGET_SCOREBOARD -#undef USE_FCNTL_SERIALIZED_ACCEPT -#undef USE_FLOCK_SERIALIZED_ACCEPT +#undef HAVE_FCNTL_SERIALIZED_ACCEPT +#undef HAVE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_NONE_SERIALIZED_ACCEPT #define USE_LONGJMP #undef NO_KILLPG #undef NO_SETSID @@ -753,7 +765,7 @@ typedef int rlim_t; #define NO_KILLPG #undef NO_SETSID #define bzero(a,b) memset(a,0,b) -#define USE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #define HAVE_MMAP 1 #define USE_MMAP_SCOREBOARD #define USE_MMAP_FILES @@ -774,7 +786,7 @@ typedef int rlim_t; #define MAXSOCKETS 2048 #define USE_OS2_SCOREBOARD #define NO_RELIABLE_PIPED_LOGS -#define USE_OS2SEM_SERIALIZED_ACCEPT +#define HAVE_OS2SEM_SERIALIZED_ACCEPT #define SINGLE_LISTEN_UNSERIALIZED_ACCEPT #define NO_SLACK #define FOPEN_REQUIRES_T @@ -788,7 +800,7 @@ typedef int rlim_t; #ifndef __MACHTEN_68K__ #define __MACHTEN_68K__ #endif -#define USE_FLOCK_SERIALIZED_ACCEPT +#define HAVE_FLOCK_SERIALIZED_ACCEPT #define NO_USE_SIGACTION #define JMP_BUF sigjmp_buf #define USE_LONGJMP @@ -796,7 +808,7 @@ typedef int rlim_t; #else #define HAVE_SHMGET 1 #define USE_SHMGET_SCOREBOARD -#define USE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #endif /* Convex OS v11 */ @@ -821,7 +833,7 @@ typedef int rlim_t; #undef NO_SETSID #define HAVE_SHMGET 1 #define USE_SHMGET_SCOREBOARD -#define USE_FCNTL_SERIALIZED_ACCEPT +#define HAVE_FCNTL_SERIALIZED_ACCEPT #define HAVE_SYSLOG 1 #elif defined(NEWSOS) @@ -909,7 +921,7 @@ typedef int rlim_t; #define USE_SHMGET_SCOREBOARD /*#define USE_TPF_SCOREBOARD*/ #define USE_TPF_ACCEPT -#define USE_TPF_CORE_SERIALIZED_ACCEPT +#define HAVE_TPF_CORE_SERIALIZED_ACCEPT #define USE_TPF_SELECT #define S_IREAD S_IRUSR #define S_IWRITE S_IWUSR @@ -931,7 +943,7 @@ typedef int rlim_t; #define USE_SHMGET_SCOREBOARD #define USE_MMAP_FILES #define NEED_UNION_SEMUN -#define USE_SYSVSEM_SERIALIZED_ACCEPT +#define HAVE_SYSVSEM_SERIALIZED_ACCEPT #define _POSIX_SOURCE #include #ifdef SIGDUMP /* SIGDUMP is not defined by OS/390 v1r2 */ @@ -1159,6 +1171,32 @@ int setrlimit(int, struct rlimit *); #undef USE_SHMGET_SCOREBOARD #endif +/* A USE_FOO_SERIALIZED_ACCEPT implies a HAVE_FOO_SERIALIZED_ACCEPT */ +#if defined(USE_USLOCK_SERIALIZED_ACCEPT) && !defined(HAVE_USLOCK_SERIALIZED_ACCEPT) +#define HAVE_USLOCK_SERIALIZED_ACCEPT +#endif +#if defined(USE_PTHREAD_SERIALIZED_ACCEPT) && !defined(HAVE_PTHREAD_SERIALIZED_ACCEPT) +#define HAVE_PTHREAD_SERIALIZED_ACCEPT +#endif +#if defined(USE_SYSVSEM_SERIALIZED_ACCEPT) && !defined(HAVE_SYSVSEM_SERIALIZED_ACCEPT) +#define HAVE_SYSVSEM_SERIALIZED_ACCEPT +#endif +#if defined(USE_FCNTL_SERIALIZED_ACCEPT) && !defined(HAVE_FCNTL_SERIALIZED_ACCEPT) +#define HAVE_FCNTL_SERIALIZED_ACCEPT +#endif +#if defined(USE_FLOCK_SERIALIZED_ACCEPT) && !defined(HAVE_FLOCK_SERIALIZED_ACCEPT) +#define HAVE_FLOCK_SERIALIZED_ACCEPT +#endif +#if defined(USE_OS2SEM_SERIALIZED_ACCEPT) && !defined(HAVE_OS2SEM_SERIALIZED_ACCEPT) +#define HAVE_OS2SEM_SERIALIZED_ACCEPT +#endif +#if defined(USE_TPF_CORE_SERIALIZED_ACCEPT) && !defined(HAVE_TPF_CORE_SERIALIZED_ACCEPT) +#define HAVE_TPF_CORE_SERIALIZED_ACCEPT +#endif +#if defined(USE_NONE_SERIALIZED_ACCEPT) && !defined(HAVE_NONE_SERIALIZED_ACCEPT) +#define HAVE_NONE_SERIALIZED_ACCEPT +#endif + #ifndef LOGNAME_MAX #define LOGNAME_MAX 25 #endif diff --git a/src/include/http_main.h b/src/include/http_main.h index cc047eb5034..f480658a3b0 100644 --- a/src/include/http_main.h +++ b/src/include/http_main.h @@ -130,6 +130,10 @@ API_EXPORT(int) ap_check_alarm(void); void setup_signal_names(char *prefix); +/* functions for determination and setting of accept() mutexing */ +char *ap_default_mutex_method(void); +char *ap_init_mutex_method(char *t); + #ifndef NO_OTHER_CHILD /* * register an other_child -- a child which the main loop keeps track of diff --git a/src/lib/sdbm/sdbm_lock.c b/src/lib/sdbm/sdbm_lock.c index a8c2fa437ab..aa0f148ba71 100644 --- a/src/lib/sdbm/sdbm_lock.c +++ b/src/lib/sdbm/sdbm_lock.c @@ -9,12 +9,13 @@ /* The locking support: * Try to determine whether we should use fcntl() or flock(). * Would be better ap_config.h could provide this... :-( + * Small monkey business to ensure that fcntl is preferred, + * unless we specified USE_FLOCK_SERIALIZED_ACCEPT during compile. */ -#if defined(USE_FCNTL_SERIALIZED_ACCEPT) +#if defined(HAVE_FCNTL_SERIALIZED_ACCEPT) && !defined(USE_FLOCK_SERIALIZED_ACCEPT) #define USE_FCNTL 1 #include -#endif -#if defined(USE_FLOCK_SERIALIZED_ACCEPT) +#elif defined(HAVE_FLOCK_SERIALIZED_ACCEPT) #define USE_FLOCK 1 #include #endif diff --git a/src/main/http_core.c b/src/main/http_core.c index 0dd28f3b961..e845f1a96d1 100644 --- a/src/main/http_core.c +++ b/src/main/http_core.c @@ -1135,6 +1135,10 @@ static const char *set_add_default_charset(cmd_parms *cmd, } return NULL; } +static const char *set_accept_mutex(cmd_parms *cmd, void *dummy, char *arg) +{ + return ap_init_mutex_method(arg); +} static const char *set_document_root(cmd_parms *cmd, void *dummy, char *arg) { @@ -3215,6 +3219,34 @@ static const command_rec core_cmds[] = { (void*)XtOffsetOf(core_dir_config, limit_req_body), OR_ALL, TAKE1, "Limit (in bytes) on maximum size of request message body" }, +{ "AcceptMutex", set_accept_mutex, NULL, RSRC_CONF, TAKE1, + "Serialized Accept Mutex; the methods " +#ifdef HAVE_USLOCK_SERIALIZED_ACCEPT + "'uslock' " +#endif +#ifdef HAVE_PTHREAD_SERIALIZED_ACCEPT + "'pthread' " +#endif +#ifdef HAVE_SYSVSEM_SERIALIZED_ACCEPT + "'sysvsem' " +#endif +#ifdef HAVE_FCNTL_SERIALIZED_ACCEPT + "'fcntl' " +#endif +#ifdef HAVE_FLOCK_SERIALIZED_ACCEPT + "'flock' " +#endif +#ifdef HAVE_OS2SEM_SERIALIZED_ACCEPT + "'os2sem' " +#endif +#ifdef HAVE_TPF_CORE_SERIALIZED_ACCEPT + "'tpfcore' " +#endif +#ifdef HAVE_NONE_SERIALIZED_ACCEPT + "'none' " +#endif + "are compiled in" +}, /* EBCDIC Conversion directives: */ #ifdef CHARSET_EBCDIC diff --git a/src/main/http_main.c b/src/main/http_main.c index 3e884cda032..3a7e148b9ef 100644 --- a/src/main/http_main.c +++ b/src/main/http_main.c @@ -258,6 +258,17 @@ API_VAR_EXPORT int ap_daemons_limit=0; time_t ap_restart_time=0; API_VAR_EXPORT int ap_suexec_enabled = 0; int ap_listenbacklog=0; + +struct accept_mutex_methods_s { + void (*child_init)(pool *p); + void (*init)(pool *p); + void (*on)(void); + void (*off)(void); + char *name; +}; +typedef struct accept_mutex_methods_s accept_mutex_methods_s; +accept_mutex_methods_s *amutex; + #ifdef SO_ACCEPTFILTER int ap_acceptfilter = #ifdef AP_ACCEPTFILTER_OFF @@ -503,7 +514,20 @@ static void clean_child_exit(int code) exit(code); } -#if defined(USE_FCNTL_SERIALIZED_ACCEPT) || defined(USE_FLOCK_SERIALIZED_ACCEPT) +/* + * Start of accept() mutex fluff: + * Concept: Each method has it's own distinct set of mutex functions, + * which it shoves in a nice struct for us. We then pick + * which struct to use. We tell Apache which methods we + * support via HAVE_FOO_SERIALIZED_ACCEPT. We can + * specify the default via USE_FOO_SERIALIZED_ACCEPT + * (this pre-1.3.21 builds which use that at the command- + * line during builds work as expected). Without a set + * method, we pick the 1st from the following order: + * uslock, pthread, sysvsem, fcntl, flock, os2sem, tpfcore and none. + */ + +#if defined(HAVE_FCNTL_SERIALIZED_ACCEPT) || defined(HAVE_FLOCK_SERIALIZED_ACCEPT) static void expand_lock_fname(pool *p) { /* XXXX possibly bogus cast */ @@ -512,15 +536,13 @@ static void expand_lock_fname(pool *p) } #endif -#if defined (USE_USLOCK_SERIALIZED_ACCEPT) - +#if defined (HAVE_USLOCK_SERIALIZED_ACCEPT) #include - static ulock_t uslock = NULL; -#define accept_mutex_child_init(x) +#define accept_mutex_child_init_uslock(x) -static void accept_mutex_init(pool *p) +static void accept_mutex_init_uslock(pool *p) { ptrdiff_t old; usptr_t *us; @@ -551,7 +573,7 @@ static void accept_mutex_init(pool *p) } } -static void accept_mutex_on(void) +static void accept_mutex_on_uslock(void) { switch (ussetlock(uslock)) { case 1: @@ -566,7 +588,7 @@ static void accept_mutex_on(void) } } -static void accept_mutex_off(void) +static void accept_mutex_off_uslock(void) { if (usunsetlock(uslock) == -1) { perror("usunsetlock"); @@ -574,7 +596,16 @@ static void accept_mutex_off(void) } } -#elif defined (USE_PTHREAD_SERIALIZED_ACCEPT) +accept_mutex_methods_s accept_mutex_uslock_s = { + NULL, + accept_mutex_init_uslock, + accept_mutex_on_uslock, + accept_mutex_off_uslock, + "uslock" +}; +#endif + +#if defined (HAVE_PTHREAD_SERIALIZED_ACCEPT) /* This code probably only works on Solaris ... but it works really fast * on Solaris. Note that pthread mutexes are *NOT* released when a task @@ -589,7 +620,7 @@ static int have_accept_mutex; static sigset_t accept_block_mask; static sigset_t accept_previous_mask; -static void accept_mutex_child_cleanup(void *foo) +static void accept_mutex_child_cleanup_pthread(void *foo) { if (accept_mutex != (void *)(caddr_t)-1 && have_accept_mutex) { @@ -597,12 +628,12 @@ static void accept_mutex_child_cleanup(void *foo) } } -static void accept_mutex_child_init(pool *p) +static void accept_mutex_child_init_pthread(pool *p) { - ap_register_cleanup(p, NULL, accept_mutex_child_cleanup, ap_null_cleanup); + ap_register_cleanup(p, NULL, accept_mutex_child_cleanup_pthread, ap_null_cleanup); } -static void accept_mutex_cleanup(void *foo) +static void accept_mutex_cleanup_pthread(void *foo) { if (accept_mutex != (void *)(caddr_t)-1 && munmap((caddr_t) accept_mutex, sizeof(*accept_mutex))) { @@ -611,7 +642,7 @@ static void accept_mutex_cleanup(void *foo) accept_mutex = (void *)(caddr_t)-1; } -static void accept_mutex_init(pool *p) +static void accept_mutex_init_pthread(pool *p) { pthread_mutexattr_t mattr; int fd; @@ -645,10 +676,10 @@ static void accept_mutex_init(pool *p) sigdelset(&accept_block_mask, SIGHUP); sigdelset(&accept_block_mask, SIGTERM); sigdelset(&accept_block_mask, SIGUSR1); - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + ap_register_cleanup(p, NULL, accept_mutex_cleanup_pthread, ap_null_cleanup); } -static void accept_mutex_on(void) +static void accept_mutex_on_pthread(void) { int err; @@ -670,7 +701,7 @@ static void accept_mutex_on(void) ap_unblock_alarms(); } -static void accept_mutex_off(void) +static void accept_mutex_off_pthread(void) { int err; @@ -692,7 +723,16 @@ static void accept_mutex_off(void) } } -#elif defined (USE_SYSVSEM_SERIALIZED_ACCEPT) +accept_mutex_methods_s accept_mutex_pthread_s = { + accept_mutex_child_init_pthread, + accept_mutex_init_pthread, + accept_mutex_on_pthread, + accept_mutex_off_pthread, + "pthread" +}; +#endif + +#if defined (HAVE_SYSVSEM_SERIALIZED_ACCEPT) #include #include @@ -716,7 +756,7 @@ static struct sembuf op_off; * means we have to be sure to clean this up or else we'll leak * semaphores. */ -static void accept_mutex_cleanup(void *foo) +static void accept_mutex_cleanup_sysvsem(void *foo) { union semun ick; @@ -727,9 +767,9 @@ static void accept_mutex_cleanup(void *foo) semctl(sem_id, 0, IPC_RMID, ick); } -#define accept_mutex_child_init(x) +#define accept_mutex_child_init_sysvsem(x) -static void accept_mutex_init(pool *p) +static void accept_mutex_init_sysvsem(pool *p) { union semun ick; struct semid_ds buf; @@ -758,7 +798,7 @@ static void accept_mutex_init(pool *p) exit(APEXIT_INIT); } } - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + ap_register_cleanup(p, NULL, accept_mutex_cleanup_sysvsem, ap_null_cleanup); /* pre-initialize these */ op_on.sem_num = 0; @@ -769,7 +809,7 @@ static void accept_mutex_init(pool *p) op_off.sem_flg = SEM_UNDO; } -static void accept_mutex_on(void) +static void accept_mutex_on_sysvsem(void) { while (semop(sem_id, &op_on, 1) < 0) { if (errno != EINTR) { @@ -779,7 +819,7 @@ static void accept_mutex_on(void) } } -static void accept_mutex_off(void) +static void accept_mutex_off_sysvsem(void) { while (semop(sem_id, &op_off, 1) < 0) { if (errno != EINTR) { @@ -789,19 +829,28 @@ static void accept_mutex_off(void) } } -#elif defined(USE_FCNTL_SERIALIZED_ACCEPT) +accept_mutex_methods_s accept_mutex_sysvsem_s = { + NULL, + accept_mutex_init_sysvsem, + accept_mutex_on_sysvsem, + accept_mutex_off_sysvsem, + "sysvsem" +}; +#endif + +#if defined(HAVE_FCNTL_SERIALIZED_ACCEPT) static struct flock lock_it; static struct flock unlock_it; static int lock_fd = -1; -#define accept_mutex_child_init(x) +#define accept_mutex_child_init_fcntl(x) /* * Initialize mutex lock. * Must be safe to call this on a restart. */ -static void accept_mutex_init(pool *p) +static void accept_mutex_init_fcntl(pool *p) { lock_it.l_whence = SEEK_SET; /* from current point */ @@ -825,7 +874,7 @@ static void accept_mutex_init(pool *p) unlink(ap_lock_fname); } -static void accept_mutex_on(void) +static void accept_mutex_on_fcntl(void) { int ret; @@ -842,7 +891,7 @@ static void accept_mutex_on(void) } } -static void accept_mutex_off(void) +static void accept_mutex_off_fcntl(void) { int ret; @@ -858,11 +907,20 @@ static void accept_mutex_off(void) } } -#elif defined(USE_FLOCK_SERIALIZED_ACCEPT) +accept_mutex_methods_s accept_mutex_fcntl_s = { + NULL, + accept_mutex_init_fcntl, + accept_mutex_on_fcntl, + accept_mutex_off_fcntl, + "fcntl" +}; +#endif -static int lock_fd = -1; +#if defined(HAVE_FLOCK_SERIALIZED_ACCEPT) + +static int flock_fd = -1; -static void accept_mutex_cleanup(void *foo) +static void accept_mutex_cleanup_flock(void *foo) { unlink(ap_lock_fname); } @@ -871,11 +929,11 @@ static void accept_mutex_cleanup(void *foo) * Initialize mutex lock. * Done by each child at it's birth */ -static void accept_mutex_child_init(pool *p) +static void accept_mutex_child_init_flock(pool *p) { - lock_fd = ap_popenf(p, ap_lock_fname, O_WRONLY, 0600); - if (lock_fd == -1) { + flock_fd = ap_popenf(p, ap_lock_fname, O_WRONLY, 0600); + if (flock_fd == -1) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "Child cannot open lock file: %s", ap_lock_fname); clean_child_exit(APEXIT_CHILDINIT); @@ -886,24 +944,24 @@ static void accept_mutex_child_init(pool *p) * Initialize mutex lock. * Must be safe to call this on a restart. */ -static void accept_mutex_init(pool *p) +static void accept_mutex_init_flock(pool *p) { expand_lock_fname(p); unlink(ap_lock_fname); - lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600); - if (lock_fd == -1) { + flock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600); + if (flock_fd == -1) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "Parent cannot open lock file: %s", ap_lock_fname); exit(APEXIT_INIT); } - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + ap_register_cleanup(p, NULL, accept_mutex_cleanup_flock, ap_null_cleanup); } -static void accept_mutex_on(void) +static void accept_mutex_on_flock(void) { int ret; - while ((ret = flock(lock_fd, LOCK_EX)) < 0 && errno == EINTR) + while ((ret = flock(flock_fd, LOCK_EX)) < 0 && errno == EINTR) continue; if (ret < 0) { @@ -913,20 +971,29 @@ static void accept_mutex_on(void) } } -static void accept_mutex_off(void) +static void accept_mutex_off_flock(void) { - if (flock(lock_fd, LOCK_UN) < 0) { + if (flock(flock_fd, LOCK_UN) < 0) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "flock: LOCK_UN: Error freeing accept lock. Exiting!"); clean_child_exit(APEXIT_CHILDFATAL); } } -#elif defined(USE_OS2SEM_SERIALIZED_ACCEPT) +accept_mutex_methods_s accept_mutex_flock_s = { + accept_mutex_child_init_flock, + accept_mutex_init_flock, + accept_mutex_on_flock, + accept_mutex_off_flock, + "flock" +}; +#endif + +#if defined(HAVE_OS2SEM_SERIALIZED_ACCEPT) static HMTX lock_sem = -1; -static void accept_mutex_cleanup(void *foo) +static void accept_mutex_cleanup_os2sem(void *foo) { DosReleaseMutexSem(lock_sem); DosCloseMutexSem(lock_sem); @@ -936,7 +1003,7 @@ static void accept_mutex_cleanup(void *foo) * Initialize mutex lock. * Done by each child at it's birth */ -static void accept_mutex_child_init(pool *p) +static void accept_mutex_child_init_os2sem(pool *p) { int rc = DosOpenMutexSem(NULL, &lock_sem); @@ -945,7 +1012,7 @@ static void accept_mutex_child_init(pool *p) "Child cannot open lock semaphore, rc=%d", rc); clean_child_exit(APEXIT_CHILDINIT); } else { - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + ap_register_cleanup(p, NULL, accept_mutex_cleanup_os2sem, ap_null_cleanup); } } @@ -953,7 +1020,7 @@ static void accept_mutex_child_init(pool *p) * Initialize mutex lock. * Must be safe to call this on a restart. */ -static void accept_mutex_init(pool *p) +static void accept_mutex_init_os2sem(pool *p) { int rc = DosCreateMutexSem(NULL, &lock_sem, DC_SEM_SHARED, FALSE); @@ -963,10 +1030,10 @@ static void accept_mutex_init(pool *p) exit(APEXIT_INIT); } - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + ap_register_cleanup(p, NULL, accept_mutex_cleanup_os2sem, ap_null_cleanup); } -static void accept_mutex_on(void) +static void accept_mutex_on_os2sem(void) { int rc = DosRequestMutexSem(lock_sem, SEM_INDEFINITE_WAIT); @@ -977,7 +1044,7 @@ static void accept_mutex_on(void) } } -static void accept_mutex_off(void) +static void accept_mutex_off_os2sem(void) { int rc = DosReleaseMutexSem(lock_sem); @@ -988,52 +1055,201 @@ static void accept_mutex_off(void) } } -#elif defined(USE_TPF_CORE_SERIALIZED_ACCEPT) +accept_mutex_methods_s accept_mutex_os2sem_s = { + accept_mutex_child_init_os2sem, + accept_mutex_init_os2sem, + accept_mutex_on_os2sem, + accept_mutex_off_os2sem, + "os2sem" +}; +#endif + +#if defined(HAVE_TPF_CORE_SERIALIZED_ACCEPT) static int tpf_core_held; -static void accept_mutex_cleanup(void *foo) +static void accept_mutex_cleanup_tpfcore(void *foo) { if(tpf_core_held) coruc(RESOURCE_KEY); } -#define accept_mutex_init(x) +#define accept_mutex_init_tpfcore(x) -static void accept_mutex_child_init(pool *p) +static void accept_mutex_child_init_tpfcore(pool *p) { - ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + ap_register_cleanup(p, NULL, accept_mutex_cleanup_tpfcore, ap_null_cleanup); tpf_core_held = 0; } -static void accept_mutex_on(void) +static void accept_mutex_on_tpfcore(void) { corhc(RESOURCE_KEY); tpf_core_held = 1; ap_check_signals(); } -static void accept_mutex_off(void) +static void accept_mutex_off_tpfcore(void) { coruc(RESOURCE_KEY); tpf_core_held = 0; ap_check_signals(); } -#else -/* Default --- no serialization. Other methods *could* go here, - * as #elifs... - */ +accept_mutex_methods_s accept_mutex_tpfcore_s = { + accept_mutex_child_init_tpfcore, + accept_mutex_init_tpfcore, + accept_mutex_on_tpfcore, + accept_mutex_off_tpfcore, + "tpfcore" +}; +#endif + +/* Generally, HAVE_NONE_SERIALIZED_ACCEPT simply won't work but + * for testing purposes, here it is... */ +#if defined HAVE_NONE_SERIALIZED_ACCEPT #if !defined(MULTITHREAD) /* Multithreaded systems don't complete between processes for * the sockets. */ #define NO_SERIALIZED_ACCEPT -#define accept_mutex_child_init(x) -#define accept_mutex_init(x) -#define accept_mutex_on() -#define accept_mutex_off() +#endif + +accept_mutex_methods_s accept_mutex_none_s = { + NULL, + NULL, + NULL, + NULL, + "none" +}; #endif + +#define AP_FPTR1(x,y) { if (x) ((* x)(y)); } +#define AP_FPTR0(x) { if (x) ((* x)()); } + +#define accept_mutex_child_init(x) AP_FPTR1(amutex->child_init,x) +#define accept_mutex_init(x) AP_FPTR1(amutex->init,x) +#define accept_mutex_off() AP_FPTR0(amutex->off) +#define accept_mutex_on() AP_FPTR0(amutex->on) + +char *ap_default_mutex_method(void) +{ + char *t; +#if defined USE_USLOCK_SERIALIZED_ACCEPT + t = "uslock"; +#elif defined USE_PTHREAD_SERIALIZED_ACCEPT + t = "pthread"; +#elif defined USE_SYSVSEM_SERIALIZED_ACCEPT + t = "sysvsem"; +#elif defined USE_FCNTL_SERIALIZED_ACCEPT + t = "fcntl"; +#elif defined USE_FLOCK_SERIALIZED_ACCEPT + t = "flock"; +#elif defined USE_OS2SEM_SERIALIZED_ACCEPT + t = "os2sem"; +#elif defined USE_TPF_CORE_SERIALIZED_ACCEPT + t = "tpfcore"; +#elif defined USE_NONE_SERIALIZED_ACCEPT + t = "none"; +#else + t = "default"; +#endif +#if defined HAVE_USLOCK_SERIALIZED_ACCEPT + if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"uslock")))) + return "uslock"; +#endif +#if defined HAVE_PTHREAD_SERIALIZED_ACCEPT + if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"pthread")))) + return "pthread"; +#endif +#if defined HAVE_SYSVSEM_SERIALIZED_ACCEPT + if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"sysvsem")))) + return "sysvsem"; +#endif +#if defined HAVE_FCNTL_SERIALIZED_ACCEPT + if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"fcntl")))) + return "fcntl"; +#endif +#if defined HAVE_FLOCK_SERIALIZED_ACCEPT + if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"flock")))) + return "flock"; +#endif +#if defined HAVE_OS2SEM_SERIALIZED_ACCEPT + if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"os2sem")))) + return "os2sem"; +#endif +#if defined HAVE_TPF_CORE_SERIALIZED_ACCEPT + if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"tpfcore")))) + return "tpfcore"; +#endif +#if defined HAVE_NONE_SERIALIZED_ACCEPT + if ((!(strcasecmp(t,"default"))) || (!(strcasecmp(t,"none")))) + return "none"; +#endif + + fprintf(stderr, "No default accept serialization known!!\n"); + exit(APEXIT_INIT); + /*NOTREACHED */ + return "unknown"; +} + +char *ap_init_mutex_method(char *t) +{ + if (!(strcasecmp(t,"default"))) + t = ap_default_mutex_method(); + +#if defined HAVE_USLOCK_SERIALIZED_ACCEPT + if (!(strcasecmp(t,"uslock"))) { + amutex = &accept_mutex_uslock_s; + } else +#endif +#if defined HAVE_PTHREAD_SERIALIZED_ACCEPT + if (!(strcasecmp(t,"pthread"))) { + amutex = &accept_mutex_pthread_s; + } else #endif +#if defined HAVE_SYSVSEM_SERIALIZED_ACCEPT + if (!(strcasecmp(t,"sysvsem"))) { + amutex = &accept_mutex_sysvsem_s; + } else +#endif +#if defined HAVE_FCNTL_SERIALIZED_ACCEPT + if (!(strcasecmp(t,"fcntl"))) { + amutex = &accept_mutex_fcntl_s; + } else +#endif +#if defined HAVE_FLOCK_SERIALIZED_ACCEPT + if (!(strcasecmp(t,"flock"))) { + amutex = &accept_mutex_flock_s; + } else +#endif +#if defined HAVE_OS2SEM_SERIALIZED_ACCEPT + if (!(strcasecmp(t,"os2sem"))) { + amutex = &accept_mutex_os2sem_s; + } else +#endif +#if defined HAVE_TPF_CORE_SERIALIZED_ACCEPT + if (!(strcasecmp(t,"tpfcore"))) { + amutex = &accept_mutex_tpfcore_s; + } else +#endif +#if defined HAVE_NONE_SERIALIZED_ACCEPT + if (!(strcasecmp(t,"none"))) { + amutex = &accept_mutex_none_s; + } else +#endif + { + if (server_conf) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf, + "Requested serialization method '%s' not available",t); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf, + "Using compiled-in default of '%s'", ap_default_mutex_method()); + } else { + fprintf(stderr, "Requested serialization method '%s' not available;\n", t); + fprintf(stderr, "Using compiled-in default of '%s'\n", ap_default_mutex_method()); + } + } + return NULL; +} /* On some architectures it's safe to do unserialized accept()s in the single * Listen case. But it's never safe to do it in the case where there's @@ -3713,20 +3929,29 @@ static void show_compile_settings(void) #ifdef NO_LINGCLOSE printf(" -D NO_LINGCLOSE\n"); #endif -#ifdef USE_FCNTL_SERIALIZED_ACCEPT - printf(" -D USE_FCNTL_SERIALIZED_ACCEPT\n"); +#ifdef HAVE_FCNTL_SERIALIZED_ACCEPT + printf(" -D HAVE_FCNTL_SERIALIZED_ACCEPT\n"); +#endif +#ifdef HAVE_FLOCK_SERIALIZED_ACCEPT + printf(" -D HAVE_FLOCK_SERIALIZED_ACCEPT\n"); #endif -#ifdef USE_FLOCK_SERIALIZED_ACCEPT - printf(" -D USE_FLOCK_SERIALIZED_ACCEPT\n"); +#ifdef HAVE_USLOCK_SERIALIZED_ACCEPT + printf(" -D HAVE_USLOCK_SERIALIZED_ACCEPT\n"); #endif -#ifdef USE_USLOCK_SERIALIZED_ACCEPT - printf(" -D USE_USLOCK_SERIALIZED_ACCEPT\n"); +#ifdef HAVE_SYSVSEM_SERIALIZED_ACCEPT + printf(" -D HAVE_SYSVSEM_SERIALIZED_ACCEPT\n"); #endif -#ifdef USE_SYSVSEM_SERIALIZED_ACCEPT - printf(" -D USE_SYSVSEM_SERIALIZED_ACCEPT\n"); +#ifdef HAVE_PTHREAD_SERIALIZED_ACCEPT + printf(" -D HAVE_PTHREAD_SERIALIZED_ACCEPT\n"); #endif -#ifdef USE_PTHREAD_SERIALIZED_ACCEPT - printf(" -D USE_PTHREAD_SERIALIZED_ACCEPT\n"); +#ifdef HAVE_OS2SEM_SERIALIZED_ACCEPT + printf(" -D HAVE_OS2SEM_SERIALIZED_ACCEPT\n"); +#endif +#ifdef HAVE_TPF_CORE_SERIALIZED_ACCEPT + printf(" -D HAVE_TPF_CORE_SERIALIZED_ACCEPT\n"); +#endif +#ifdef HAVE_NONE_SERIALIZED_ACCEPT + printf(" -D HAVE_NONE_SERIALIZED_ACCEPT\n"); #endif #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT printf(" -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT\n"); @@ -3884,7 +4109,7 @@ static void child_main(int child_num_arg) /* needs to be done before we switch UIDs so we have permissions */ reopen_scoreboard(pchild); - SAFE_ACCEPT(accept_mutex_child_init(pchild)); + SAFE_ACCEPT((accept_mutex_child_init(pchild))); set_group_privs(); #ifdef MPE @@ -3982,7 +4207,7 @@ static void child_main(int child_num_arg) */ /* Lock around "accept", if necessary */ - SAFE_ACCEPT(accept_mutex_on()); + SAFE_ACCEPT((accept_mutex_on())); for (;;) { if (ap_listeners->next != ap_listeners) { @@ -4688,6 +4913,8 @@ static void standalone_main(int argc, char **argv) ap_clear_pool(pconf); ptrans = ap_make_sub_pool(pconf); + ap_init_mutex_method(ap_default_mutex_method()); + server_conf = ap_read_config(pconf, ptrans, ap_server_confname); setup_listeners(pconf); ap_clear_pool(plog); @@ -4743,6 +4970,9 @@ static void standalone_main(int argc, char **argv) } ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, "Server built: %s", ap_get_server_built()); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf, + "Accept mutex: %s (Default: %s)", + amutex->name, ap_default_mutex_method()); restart_pending = shutdown_pending = 0; while (!restart_pending && !shutdown_pending) { diff --git a/src/modules/standard/mod_rewrite.h b/src/modules/standard/mod_rewrite.h index 47c55dbdeb8..c67bd9e2eed 100644 --- a/src/modules/standard/mod_rewrite.h +++ b/src/modules/standard/mod_rewrite.h @@ -144,12 +144,13 @@ /* The locking support: * Try to determine whether we should use fcntl() or flock(). * Would be better ap_config.h could provide this... :-( + * Small monkey business to ensure that fcntl is preferred, + * unless we specified USE_FLOCK_SERIALIZED_ACCEPT during compile. */ -#if defined(USE_FCNTL_SERIALIZED_ACCEPT) +#if defined(HAVE_FCNTL_SERIALIZED_ACCEPT) && !defined(USE_FLOCK_SERIALIZED_ACCEPT) #define USE_FCNTL 1 #include -#endif -#if defined(USE_FLOCK_SERIALIZED_ACCEPT) +#elif defined(HAVE_FLOCK_SERIALIZED_ACCEPT) #define USE_FLOCK 1 #include #endif