Apache が AH00144 で落ちる件
事象
- Ubuntu 18.04
- apache2 (2.4.29-1ubuntu4.12)
で、apache2 プロセスが次のエラーメッセージを吐いて落ちるという連絡を受けて調べました。これはその原因と対処法のメモです。
[mpm_prefork:emerg] [pid 18633] (43)Identifier removed: AH00144: couldn't grab the accept mutex [mpm_prefork:emerg] [pid 18632] (43)Identifier removed: AH00144: couldn't grab the accept mutex [core:alert] [pid 18624] AH00050: Child 18632 returned a Fatal error... Apache is exiting! [:emerg] [pid 18624] AH02818: MPM run failed, exiting
原因
簡単にいうと、Apache が Mutex に使っているセマフォを systemd-logind が消してしまうのが原因です。
Apache の Mutex
Mutex ディレクティブ のデフォルトは Mutex default
で、どの機構が採用されるかは APR に委ねられています。
どの機構が採用されるかはこのようにして確認できます。
$ cat mutex-default.c #include <apr_portable.h> int main(int argc, char** argv) { printf("%s\n", apr_proc_mutex_defname()); return 0; } $ gcc $(apr-config --includes) mutex-default.c $(apr-config --link-ld) $ ./a.out sysvsem
存在する IPC セマフォなどの確認は ipcs
コマンドでできます。
Apache が起動していれば、セマフォがいくつか表示されるはずです。
$ ipcs -a ------ Message Queues -------- key msqid owner perms used-bytes messages ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status ------ Semaphore Arrays -------- key semid owner perms nsems 0x00000000 5111808 gyoza 600 1 0x00000000 5144577 gyoza 600 1 0x00000000 5046274 gyoza 600 1 0x00000000 5177347 gyoza 600 1 0x00000000 5210116 gyoza 600 1
systemd-logind の RemoveIPC
systemd-logind はデフォルトで RemoveIPC=yes
になっています。
RemoveIPC
とは logind.conf(5) によれば次のように説明されています。
RemoveIPC= Controls whether System V and POSIX IPC objects belonging to the user shall be removed when the user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users are excluded from the effect of this setting. Defaults to "yes".
つまり、
- logind 管理下のセッションが全てなくなるときに、そのユーザーの IPC セマフォなどを全て削除する
- ただし、root とシステムユーザーは除外される
ということです。
システムユーザーとは、 uid が 999 以下のユーザーのことです。
再現方法
- Apache を非システムユーザー (uid が 1000 以上) で起動する → セマフォが作られる)
- その非システムユーザーで SSH ログインする
- ログアウトする → セマフォが消される
- Apache にリクエストが来るとプロセスが死ぬ
これで再現します。
通常は Apache はシステムユーザである www-data の権限で起動されるのでこの問題は発生しませんが、この環境では深淵な理由で非システムユーザーで起動していました。
対処法
内製のデーモンで IPC を使っていると同じようにハマりそうなので、後者の対処法を採用しました。
Apache でセマフォではない Mutex を使う
Mutex file:/var/lock/apache2 default
systemd-logind で IPC を消さないようにする
# install -d -o root -g root -m 755 /etc/systemd/logind.conf.d/ # cat << EOF > /etc/systemd/logind.conf.d/ipc.conf [Login] RemoveIPC=no EOF # systemctl restart systemd-logind.service