Commit bd5a48fe authored by Bill Stoddard's avatar Bill Stoddard
Browse files

Get mod_rewrite working with APR locks

This has been tested on Linux and works (with the caveats:
must use --disable-hsregex, must define NO_DBM_REWRITEMAP,
must remove Dirks March 14 patch from util.c and httpd_config.c).

Submitted by:	Paul Reder
Reviewed by:	Bill Stoddard


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84829 13f79535-47bb-0310-9956-ffa450edef68
parent effbc621
Loading
Loading
Loading
Loading
+20 −151
Changes for modules/mappers/mod_rewrite.c: 20 added lines, 151 removed lines.
Original line number Diff line number Diff line
@@ -230,7 +230,8 @@ static int proxy_available;
static int once_through = 0;

static const char *lockname;
static ap_file_t *lockfd = NULL;
static ap_lock_t *rewrite_map_lock = NULL;
static ap_lock_t *rewrite_log_lock = NULL;

/*
** +-------------------------------------------------------+
@@ -964,7 +965,12 @@ static void init_module(ap_context_t *p,
    /* check if proxy module is available */
    proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL);

    /* create the rewriting lockfile in the parent */
    /* create the rewriting lockfiles in the parent */
    if (ap_create_lock (&rewrite_log_lock, APR_MUTEX, APR_INTRAPROCESS,
                        NULL, NULL) != APR_SUCCESS)
        exit(1);    /* ugly but I can't log anything yet. This is what */
                    /*   the pre-existing rewritelock_create code did. */

    rewritelock_create(s, p);
    ap_register_cleanup(p, (void *)s, rewritelock_remove, ap_null_cleanup);

@@ -991,8 +997,9 @@ static void init_module(ap_context_t *p,

static void init_child(ap_context_t *p, server_rec *s)
{
     /* open the rewriting lockfile */
     rewritelock_open(s, p);

    if (lockname != NULL && *(lockname) != '\0')
        ap_child_init_lock (&rewrite_map_lock, lockname, p);

    /* create the lookup cache */
    cachep = init_cache(p);
@@ -2978,7 +2985,8 @@ static char *lookup_map_program(request_rec *r, ap_file_t *fpin,
    }

    /* take the lock */
    rewritelock_alloc(r);

    ap_lock(rewrite_map_lock);

    /* write out the request key */
#ifdef NO_WRITEV
@@ -3009,7 +3017,7 @@ static char *lookup_map_program(request_rec *r, ap_file_t *fpin,
    buf[i] = '\0';

    /* give the lock back */
    rewritelock_free(r);
    ap_unlock(rewrite_map_lock);

    if (strcasecmp(buf, "NULL") == 0) {
        return NULL;
@@ -3259,10 +3267,10 @@ static void rewritelog(request_rec *r, int level, const char *text, ...)
                (unsigned long)(r->server), (unsigned long)r,
                type, redir, level, str2);

    fd_lock(r, conf->rewritelogfp);
    ap_lock(rewrite_log_lock);
    nbytes = strlen(str3);
    ap_write(conf->rewritelogfp, str3, &nbytes);
    fd_unlock(r, conf->rewritelogfp);
    ap_unlock(rewrite_log_lock);

    va_end(ap);
    return;
@@ -3298,11 +3306,8 @@ static char *current_logtime(request_rec *r)

static void rewritelock_create(server_rec *s, ap_context_t *p)
{
    rewrite_server_conf *conf;
    ap_status_t rc;

    conf = ap_get_module_config(s->module_config, &rewrite_module);

    /* only operate if a lockfile is used */
    if (lockname == NULL || *(lockname) == '\0') {
        return;
@@ -3312,76 +3317,26 @@ static void rewritelock_create(server_rec *s, ap_context_t *p)
    lockname = ap_server_root_relative(p, lockname);

    /* create the lockfile */
    unlink(lockname);
    rc = ap_open(&lockfd, lockname, APR_WRITE | APR_CREATE, REWRITELOCK_MODE, p);
    rc = ap_create_lock (&rewrite_map_lock, APR_MUTEX, APR_LOCKALL, lockname, p);
    if (rc != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                     "mod_rewrite: Parent could not create RewriteLock "
                     "file %s", lockname);
        exit(1);
    }
#if !defined(OS2) && !defined(WIN32) && !defined(NETWARE)
    /* make sure the childs have access to this file */
    if (geteuid() == 0 /* is superuser */)
        chown(lockname, unixd_config.user_id, -1 /* no gid change */);
#endif

    return;
}

static void rewritelock_open(server_rec *s, ap_context_t *p)
{
    rewrite_server_conf *conf;
    ap_status_t rc;

    conf = ap_get_module_config(s->module_config, &rewrite_module);

    /* only operate if a lockfile is used */
    if (lockname == NULL || *(lockname) == '\0') {
        return;
    }

    /* open the lockfile (once per child) to get a unique fd */
    rc = ap_open(&lockfd, lockname, APR_WRITE | APR_CREATE, REWRITELOCK_MODE, p);
    if (rc != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                     "mod_rewrite: Child could not open RewriteLock "
                     "file %s", lockname);
        exit(1);
    }
    return;
}

static ap_status_t rewritelock_remove(void *data)
{
    /* only operate if a lockfile is used */
    if (lockname == NULL || *(lockname) == '\0') {
        return(-1);
    }

    /* remove the lockfile */
    unlink(lockname);
    /* destroy the rewritelock */
    ap_destroy_lock (rewrite_map_lock);
    rewrite_map_lock = NULL;
    lockname = NULL;
    lockfd = NULL;
    return(0);
}

static void rewritelock_alloc(request_rec *r)
{
    if (lockfd != NULL) {
        fd_lock(r, lockfd);
    }
    return;
}

static void rewritelock_free(request_rec *r)
{
    if (lockfd != NULL) {
        fd_unlock(r, lockfd);
    }
    return;
}


/*
** +-------------------------------------------------------+
@@ -4194,92 +4149,6 @@ static int prefix_stat(const char *path, struct stat *sb)
}


/*
**
**  File locking
**
*/

#ifdef USE_FCNTL
static struct flock   lock_it;
static struct flock unlock_it;
#endif

static void fd_lock(request_rec *r, ap_file_t *fd)
{
    int rc;
    int sys_file;

#ifdef USE_FCNTL
    lock_it.l_whence = SEEK_SET; /* from current point */
    lock_it.l_start  = 0;        /* -"- */
    lock_it.l_len    = 0;        /* until end of file */
    lock_it.l_type   = F_WRLCK;  /* set exclusive/write lock */
    lock_it.l_pid    = 0;        /* pid not actually interesting */

    ap_get_os_file(&sys_file, fd);
    while (   ((rc = fcntl(sys_file, F_SETLKW, &lock_it)) < 0)
              && (errno == EINTR)                               ) {
        continue;
    }
#endif
#ifdef USE_FLOCK
    ap_get_os_file(fd, &sys_file);
    while (   ((rc = flock(sys_file, LOCK_EX)) < 0)
              && (errno == EINTR)               ) {
        continue;
    }
#endif
#ifdef USE_LOCKING
    /* Lock the first byte, always, assume we want to append
       and seek to the end afterwards */
    ap_seek(fd, APR_SET, 0);
    ap_get_os_file(&sys_file, fd);
    rc = _locking(sys_file, _LK_LOCK, 1);
    ap_seek(fd, APR_END, 0);
#endif

    if (rc < 0) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
                     "mod_rewrite: failed to lock file descriptor");
        exit(1);
    }
    return;
}

static void fd_unlock(request_rec *r, ap_file_t *fd)
{
    int rc;
    int sys_file;

#ifdef USE_FCNTL
    unlock_it.l_whence = SEEK_SET; /* from current point */
    unlock_it.l_start  = 0;        /* -"- */
    unlock_it.l_len    = 0;        /* until end of file */
    unlock_it.l_type   = F_UNLCK;  /* unlock */
    unlock_it.l_pid    = 0;        /* pid not actually interesting */

    ap_get_os_file(&sys_file, fd);
    rc = fcntl(sys_file, F_SETLKW, &unlock_it);
#endif
#ifdef USE_FLOCK
    ap_get_os_file(fd, &sys_file);
    rc = flock(sys_file, LOCK_UN);
#endif
#ifdef USE_LOCKING
    ap_seek(fd, APR_SET, 0);
    ap_get_os_file(&sys_file, fd);
    rc = _locking(sys_file, _LK_UNLCK, 1);
    ap_seek(fd, APR_END, 0);
#endif

    if (rc < 0) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
                     "mod_rewrite: failed to unlock file descriptor");
        exit(1);
    }
}

/*
**
**  Lexicographic Compare
+0 −42
Changes for modules/mappers/mod_rewrite.h: 0 added lines, 42 removed lines.
Original line number Diff line number Diff line
@@ -145,41 +145,6 @@
#endif


    /* The locking support:
     * Try to determine whether we should use fcntl() or flock().
     * Would be better ap_config.h could provide this... :-(
     */
#if defined(USE_FCNTL_SERIALIZED_ACCEPT)
#define USE_FCNTL 1
#include <fcntl.h>
#endif
#if defined(USE_FLOCK_SERIALIZED_ACCEPT)
#define USE_FLOCK 1
#include <sys/file.h>
#endif
#if !defined(USE_FCNTL) && !defined(USE_FLOCK)
#define USE_FLOCK 1
#if !defined(MPE) && !defined(WIN32) && !defined(__TANDEM) && !defined(NETWARE)
#include <sys/file.h>
#endif
#ifndef LOCK_UN
#undef USE_FLOCK
#define USE_FCNTL 1
#include <fcntl.h>
#endif
#endif
#ifdef AIX
#undef USE_FLOCK
#define USE_FCNTL 1
#include <fcntl.h>
#endif
#ifdef WIN32
#undef USE_FCNTL
#define USE_LOCKING
#include <sys/locking.h>
#endif


/*
**
**  Some defines
@@ -459,10 +424,7 @@ static char *current_logtime(request_rec *r);

    /* rewriting lockfile support */
static void rewritelock_create(server_rec *s, ap_context_t *p);
static void rewritelock_open(server_rec *s, ap_context_t *p);
static ap_status_t rewritelock_remove(void *data);
static void rewritelock_alloc(request_rec *r);
static void rewritelock_free(request_rec *r);

    /* program map support */
static void  run_rewritemap_programs(server_rec *s, ap_context_t *p);
@@ -492,10 +454,6 @@ static int parseargline(char *str, char **a1, char **a2, char **a3);
static int    prefix_stat(const char *path, struct stat *sb);
static void   add_env_variable(request_rec *r, char *s);

    /* File locking */
static void fd_lock(request_rec *r, ap_file_t *fd);
static void fd_unlock(request_rec *r, ap_file_t *fd);

    /* Lexicographic Comparison */
static int compare_lexicography(char *cpNum1, char *cpNum2);