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