apacheモジュールでmutexを使った排他制御を実装

apacheモジュールでプロセス間通信を行う場合に、共有メモリを使うと色々問題がでてくる。
preforkの性質上、複数のapache子プロセスがフォークされており、それらがそれぞれリクエストに対する処理を行うため、共有メモリ領域の書き込み時に衝突が起きたりして、データに齟齬が発生してくる。

それを防ぐのが排他処理だ。

今回は、aprで実装済みのglobal mutexを使って排他制御する方法を説明する。

まずは、グローバでmutexを宣言する。

#include "apr_global_mutex.h"
#include "unixd.h"

apr_global_mutex_t *mutex;

次に、apache起動時のpost_configフック時に、mutexを生成する。
ifdef部はUnix系OSで必要となる。

    // global mutex 生成
    status = apr_global_mutex_create(&mutex, NULL, APR_LOCK_DEFAULT, p);
    if(status != APR_SUCCESS){
        DEBUG_SYSLOG("init: ", "Error creating global mutex.", p);
        return status;
    }
#ifdef AP_NEED_SET_MUTEX_PERMS
    status = unixd_set_global_mutex_perms(mutex);
    if(status != APR_SUCCESS){
        DEBUG_SYSLOG("init: ", "Error xrent could not set permissions on global mutex.", p);
        return status;
    }
#endif

そして、排他制御をしたい実装の前後でロック処理を実装する。

    apr_status_t status;
    // ロック
    if (apr_global_mutex_lock(mutex) != APR_SUCCESS) {
        DEBUG_SYSLOG("check_limit: ", "mutex lock failed.", r->pool);
        return OK;
    }

    //
    // 排他処理したい実装
    //

    // アンロック
    if (apr_global_mutex_unlock(mutex) != APR_SUCCESS){
        DEBUG_SYSLOG("check_limit: ", "mutex unlock failed.", r->pool);
        return OK;
    }

上記処理で排他制御を実装できる。

abコマンド等を使って検証してみると、排他制御できていることがわかる。