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コマンド等を使って検証してみると、排他制御できていることがわかる。