Apacheのモジュールロードのタイミング
モジュールをロードするコードはこのあたりだろうか。https://github.com/apache/httpd/blob/2.4.10/modules/core/mod_so.c
https://github.com/apache/httpd/blob/2.4.10/modules/core/mod_so.c
Apache からは APR の apr_dso_load() を使っているみたいなので、APRの方を覗いてみる。
https://github.com/apache/apr/blob/1.5.1/dso/unix/dso.c
複数のOSをサポートするために #ifdef が多用されててちょっと見にくいが、Linux環境であれば dlopen() が使用されるようだ。
さて、dlopen() が使用されるということが分かったので、呼び出し元に戻る。
最初に提示したコードは load_module() の中に記述されている。
これはどこからコールされているのかというと、同じ mod_so.c の中にある。
AP_INIT_TAKE2は引数を二つもつディレクティブで、
RSRC_CONFは
最後の EXEC_ON_READ は名前からも推測できますが、設定が読み込まれたときに実行されます。
実行するのは二つ目の引数である load_module() です。
設定が読み込まれたときに実行されると言うことは、graceful でも大丈夫な気がします。
モジュールをアップデートしてみる
graceful でも大丈夫そうということが分かったので、実際に試してみます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* mod_hello - Hello World for Apache 2.2 | |
* | |
* Copyright(c) 2014, KOJIMA Kazunori | |
* | |
* License: Apache License, Version 2.0 | |
* | |
* Install: | |
* $ apxs -c mod_hello.c | |
* $ sudo apxs -i -a -n hello mod_hello.la | |
*/ | |
#define CORE_PRIVATE | |
#include "httpd.h" | |
#include "http_log.h" | |
static const char *hello(cmd_parms *cmd, void *dummy, const char *arg) | |
{ | |
ap_log_error(APLOG_MARK,APLOG_NOTICE|APLOG_NOERRNO, 0 ,NULL, "Hello %s", arg); | |
return NULL; | |
} | |
static const command_rec hello_cmds[] = { | |
AP_INIT_TAKE1("Hello", hello, NULL, RSRC_CONF | EXEC_ON_READ, "Hello need one argment"), | |
{NULL} | |
}; | |
module AP_MODULE_DECLARE_DATA hello_module = | |
{ | |
STANDARD20_MODULE_STUFF, | |
NULL, /* create per-dir config */ | |
NULL, /* merge per-dir config */ | |
NULL, /* create per-server config */ | |
NULL, /* merge per-server config */ | |
hello_cmds, /* table of config file commands */ | |
NULL /* handlers registration */ | |
}; | |
上記のGistの mod_hello は Hello という設定がコンフィグに出てくると、第一引数の文字列をエラーログに出力するだけのものです。
インストールは apxs で行います。
$ apxs -c mod_hello.c
$ sudo apxs -i -a -n hello mod_hello.la
httpd.conf に設定を追加します。
+LoadModule hello_module modules/mod_hello.so
+Hello world
Apache を起動します。
$ sudo apache2ctl start
* Starting apache2 ...
[Sun Dec 07 16:11:41.528152 2014] [:notice] [pid 24998] Hello world
エラーログに "Hello world" と表示されました。続いて、モジュールを書き換えてみます。
mod_hello.c の21行目を "Hello %s" から "Hell %s" にしてみます。
再度、モジュールをコンパイル・インストールし、graceful してみます。
$ apxs -c mod_hello.c
$ sudo apxs -i -a -n hello mod_hello.la
$ sudo apache2ctl graceful
* Gracefully restarting apache2 ...
[Sun Dec 07 16:30:57.456100 2014] [:notice] [pid 25436] Hell world
変わりました。結論
- モジュールをアップデートするときは graceful で十分
参考文献
追記(2015/02/01)
Apacheモジュール更新はgracefulで十分の件、どうだろう。mod_proxy周りは設定変更時にgracefulだとなんか死ぬし、弊害が出てくる場合がある気がする
— Gentoo遊民matsuu (@matsuu) 2015, 2月 1
mod_proxy では設定が反映されなかったりすることもあるそうで、graceful だと不十分な場合もあるようです。共有メモリを使うようなモジュールだと古い設定がそのまま使われるとかありそうなので、モジュールの中身次第では注意が必要そうです。