|
mod_throttle on Mac OS X
Ole Eichhorn wrote an article about "slashdot sunscreen" based on when his "tyranny of email" was slashdotted. I read with particular interest his mention of mod_throttle, an apache module which allows control over web server activity.
There are no binaries for Mac OS X, so I pulled down the source. Uh-oh, source-level tweaking is required. I first have to choose between USE_POSIX_SERIALIZATION, USE_FCNTL_SERIALIZATION, USE_FLOCK_SERIALIZATION and USE_SYSTEM_V_SERIALIZATION. Next, I have to choose between USE_POSIX_SHARED_MEMORY and USE_SYSTEM_V_SHARED_MEMORY. There's also a #define in there named HAVE_GETPWENT. Fortunately man getpwent spits out a page acting like the functions are availible, so I can at least leave the latter alone, set to 1.
First I try USE_POSIX_SERIALIZATION/USE_POSIX_SHARED_MEMORY. While this compiled cleanly, when starting apache I got the following error:
[emerg] (22)Invalid argument: Failed to map the shared object.
Next up is USE_POSIX_SERIALIZATION/USE_SYSTEM_V_SHARED_MEMORY, which also compiled but yielded the following error:
critical_create(): cannot initialise unnamed semaphore: Function not implemented
OK, so POSIX's out of the question. POSIX is more modern than System V APIs so it was worth a shot. I thought Mac OS X was POSIX-studly, guess I was wrong. Let's try the default System V settings: USE_SYSTEM_V_SERIALIZATION/USE_SYSTEM_V_SHARED_MEMORY. Rats, compiler error:
mod_throttle.c:726: redefinition of `union semun'
Looking at the code referenced by the compiler error yielded this insight:
#if (defined(__GNU_LIBRARY__) && (!defined(_SEM_SEMUN_UNDEFINED))) || defined(__FreeBSD__) || defined(__NetBSD__)
/* union semun is defined by including <sys/sem.h> */
#else
/* X/OPEN says we have to define it ourselves (twits). */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short int *array; /* array for GETALL, SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
#endif
Ah yes, twits at work again. But Mac OS X ain't no X/OPEN, so another special-case is needed:
#if (defined(__GNU_LIBRARY__) && (!defined(_SEM_SEMUN_UNDEFINED))) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE_CC__)
/* union semun is defined by including <sys/sem.h> */
#else
/* X/OPEN says we have to define it ourselves (twits). */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short int *array; /* array for GETALL, SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
#endif
Bingo, clean compile, install, and apache happily starts. I added the following lines to my httpd.conf file:
# Put this AFTER the preexisting LoadModules series.
LoadModule throttle_module libexec/httpd/mod_throttle.so
# Put this AFTER the preexisting AddModules series.
AddModule mod_throttle.c
# Put this any place after LoadModule/AddModule.
<IfModule mod_throttle.c>
ThrottlePolicy request 15 5s
<Location /throttle-status>
SetHandler throttle-status
</Location>
</IfModule>
It's important that those LoadModule/AddModule lines come at the end of the series -- it didn't work if they were first. To save you the pain of trying to compile mod_throttle yourself, I'm posting my binary.
Update: Chris Ridd tells me I should check for __MACH__ being defined, not __APPLE_CC__. The latter simply tests for Apple's compiler, not Mach itself (which underlies Mac OS X). Thanks, Chris. By the way, cute kid, love the name.
Update: David La Monaca writes, informing me that if you want to deploy mod_throttle across multiple virtual hosts, you need to add a ThrottlePolicy directive per each <VirtualHost>.
Tuesday, April 01, 2003
12:00 AM
|