Translated message

A translation of this page exists in English.

Warning message

This translation is outdated. For the most up-to-date information, please refer to the English version.

システムログに「Assertion ‘pid ›= 1’ failed at src/core/unit.c:1997, function unit_watch_pid(). Aborting.」が表示され、systemd がハングして応答しない

Solution Verified - Updated -

Environment

  • Red Hat Enterprise Linux (RHEL) 7
  • systemd-219-30.el7_3.7

Issue

  • systemd はメモリープレッシャーのため、複数のホストで応答せず、正しく動作しません。通常のソケットでの接続を拒否しているため、systemctl および journalctl などのコマンドはハングするか失敗します。 また、継承するプロセスを取得できず (pid 1 の重要な責任)、数万ものゾンビがたまっています。以下は、/var/log/messages 内に表示されます。
May 20 06:47:56 host.example.com systemd[1]: Failed to fork: Cannot allocate memory
May 20 06:47:56 host.example.com systemd[1]: Assertion 'pid >= 1' failed at src/core/unit.c:1997, function unit_watch_pid(). Aborting.
May 20 06:47:56 host.example.com systemd[1]: Caught <ABRT>, cannot fork for core dump: Cannot allocate memory
May 20 06:47:56 host.example.com systemd[1]: Freezing execution.

Resolution

この問題は、以下で修正されました。
systemd-219-57.el7 (RHEL 7.5 でリリース)
systemd-219-42.el7_4.9 (RHEL 7.4.Z Stream 用)
systemd-219-19.el7_2.21 (RHEL 7.2.EUS Stream 用)

systemd のハング状態から回復するには、システムの再起動を推奨します。これには、「-f」または「-ff」フラグを systemctl reboot に渡す必要があります。このためには、以下の情報が適用されます。

       -f, --force
           When used with enable, overwrite any existing conflicting symlinks.

           When used with halt, poweroff, reboot or kexec, execute the selected operation without shutting down all
           units. However, all processes will be killed forcibly and all file systems are unmounted or remounted
           read-only. This is hence a drastic but relatively safe option to request an immediate reboot. If --force
           is specified twice for these operations, they will be executed immediately without terminating any
           processes or unmounting any file systems. Warning: specifying --force twice with any of these operations
           might result in data loss.

Root Cause

systemd ユーティリティーは、システムがメモリープレッシャーの状態にある場合、以下のアップストリームコミットで文書化されている問題の影響を受けやすくなります。

commit 74129a127676e4f0edac0db4296c103e76ec6694
Author: lc85446 <lc85446@alibaba-inc.com>
Date:   Thu Nov 26 11:46:40 2015 +0800

    core:execute: fix fork() fail handling in exec_spawn()

        If pid < 0 after fork(), 0 is always returned because r =
        exec_context_load_environment() has exited successfully.

        This will make the caller of exec_spawn() not able to handle
        the fork() error case and make systemd abort assert() possibly.

diff --git a/src/core/execute.c b/src/core/execute.c
index 677480c..4f67a9d 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -2056,7 +2056,7 @@ int exec_spawn(Unit *unit,
                    NULL);
         pid = fork();
         if (pid < 0)
-                return log_unit_error_errno(unit, r, "Failed to fork: %m");
+                return log_unit_error_errno(unit, errno, "Failed to fork: %m");

         if (pid == 0) {
                 int exit_status;

上記の誤ったエラー処理動作が原因で、pid メンバーは 1 以上ではないため、以下のアサーションは失敗します。

int unit_watch_pid(Unit *u, pid_t pid) {
        int q, r;

        assert(u);
        assert(pid >= 1);

        /* Watch a specific PID. We only support one or two units
         * watching each PID for now, not more. */

        r = set_ensure_allocated(&u->pids, NULL);
        if (r < 0)
                return r;

        r = hashmap_ensure_allocated(&u->manager->watch_pids1, NULL);
        if (r < 0)
                return r;

        r = hashmap_put(u->manager->watch_pids1, LONG_TO_PTR(pid), u);
        if (r == -EEXIST) {
                r = hashmap_ensure_allocated(&u->manager->watch_pids2, NULL);
                if (r < 0)
                        return r;

                r = hashmap_put(u->manager->watch_pids2, LONG_TO_PTR(pid), u);
        }

        q = set_put(u->pids, LONG_TO_PTR(pid));
        if (q < 0)
                return q;

        return r;
}

Diagnostic Steps

  • /var/log/messages または同様の一般的なシステムログファイルで、以下のメッセージが表示されていることを確認します。
Assertion 'pid >= 1' failed at src/core/unit.c:1997, function unit_watch_pid(). Aborting.

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments