プロセスを停止する(TASK_UNINTERRUPTIBLE にする)方法

検証のために TASK_UNINTERRUPTIBLE なプロセスを作りたくなったときのメモ。

cgroup の freezer サブシステムを利用してプロセスを停止する(TASK_UNINTERRUPTIBLE にする) 方法を記載する。 検証は EC2 の Ubuntu 20.0.4 LTS イメージを利用した。

まず、cgroup の freezer サブシステムがマウントされていることを確認する。

# mount | grep freezer
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)

次に、停止したいプロセス(今回は yes コマンドを無限に実行させて 1 CPU を使い切る)を起動する。

terminal A $ yes > /dev/null
terminal B # top -b | head
top - 23:34:59 up 2 min,  2 users,  load average: 0.26, 0.12, 0.04
Tasks: 121 total,   2 running, 119 sleeping,   0 stopped,   0 zombie
%Cpu(s): 38.7 us, 12.9 sy,  0.0 ni, 48.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3933.7 total,   3075.3 free,    237.1 used,    621.4 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   3470.2 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   1409 ubuntu    20   0    7228    532    464 R 100.0   0.0   0:06.92 yes
      1 root      20   0  101816  11520   8548 S   0.0   0.3   0:03.31 systemd
      2 root      20   0       0      0      0 S   0.0   0.0   0:00.00 kthreadd

次に、freezer サブシステム配下にディレクトリを作成し、停止したいプロセスの id を tasks に書き込む。

# mkdir /sys/fs/cgroup/freezer/stw
# echo 1409 > /sys/fs/cgroup/freezer/stw/tasks

最後に、 freezer.state に FROZEN を書き込むと、該当のプロセスを TASK_UNINTERRUPTIBLE に設定できる。 ps コマンドでも D+ になっているのがわかる。

# echo "FROZEN" > /sys/fs/cgroup/freezer/stw/freezer.state

# top -b | head
top - 23:36:07 up 3 min,  2 users,  load average: 0.67, 0.28, 0.11
Tasks: 121 total,   1 running, 120 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  3.1 sy,  0.0 ni, 96.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3933.7 total,   3074.6 free,    237.7 used,    621.4 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   3473.4 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
      1 root      20   0  101816  11520   8548 S   0.0   0.3   0:03.31 systemd
      2 root      20   0       0      0      0 S   0.0   0.0   0:00.00 kthreadd
      3 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_gp

# ps -aux | grep yes
ubuntu      1409 73.8  0.0   7228   532 pts/1    D+   23:34   1:09 yes

TASK_UNINTERRUPTIBLE なプロセスを用意できたが、検証内容によっては注意が必要。たとえば hung_task_panic カーネルパラメータなどの動作検証はできない(意図的に FREEZER で停止しているプロセスは処理を切り上げている)。