[英]Cgroup unexpectedly propagates SIGSTOP to the parent
我有一個小腳本來在限制 CPU 時間的 cgroup 中運行命令:
$ cat cgrun.sh
#!/bin/bash
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <bin>"
exit 1
fi
sudo cgcreate -g cpu:/cpulimit
sudo cgset -r cpu.cfs_period_us=1000000 cpulimit
sudo cgset -r cpu.cfs_quota_us=100000 cpulimit
sudo cgexec -g cpu:cpulimit sudo -u $USER "$@"
sudo cgdelete cpu:/cpulimit
我讓命令運行: ./cgrun.sh /bin/sleep 10
然后我從另一個終端發送 SIGSTOP 到 sleep 命令。 不知何故,此時父命令sudo
和cgexec
收到了這個信號。 然后,我將 SIGCONT 發送到 sleep 命令,它允許繼續睡眠。
但是此時sudo
和cgexec
被停止並且永遠不會收獲睡眠過程的僵屍。 我不明白這怎么會發生? 我該如何預防? 此外,我無法將 SIGCONT 發送到sudo
和cgexec
,因為我正在從用戶發送信號,而這些命令以 root 身份運行。
這是它在 htop 中的樣子(省略了一些列):
PID USER S CPU% MEM% TIME+ Command
1222869 user S 0.0 0.0 0:00.00 │ │ └─ /bin/bash ./cgrun.sh /bin/sleep 10
1222882 root T 0.0 0.0 0:00.00 │ │ └─ sudo cgexec -g cpu:cpulimit sudo -u user /bin/sleep 10
1222884 root T 0.0 0.0 0:00.00 │ │ └─ sudo -u desertfox /bin/sleep 10
1222887 user Z 0.0 0.0 0:00.00 │ │ └─ /bin/sleep 10
如何以不將 SIGSTOP 退回到父進程的方式創建 cgroup?
UPD
如果我使用 systemd-run 啟動進程,我不會觀察到相同的行為:
sudo systemd-run --uid=$USER -t -p CPUQuota=10% sleep 10
我不使用“cg 工具”,而是使用 shell 命令以“硬方法”來創建cpulimit cgroup(它是一個mkdir
),設置 cfs 參數(在相應的cpu.cfs_ * 文件中使用echo
命令),創建一個帶有(...)
符號的子 shell,將其移動到 cgroup(將其 pid 的echo
命令輸入到 cgroup 的tasks
文件中)並在此子 shell 中執行請求的命令。
因此, cgrun.sh
看起來像這樣:
#!/bin/bash
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <bin>" >&2
exit 1
fi
CGTREE=/sys/fs/cgroup/cpu
sudo -s <<EOF
[ ! -d ${CGTREE}/cpulimit ] && mkdir ${CGTREE}/cpulimit
echo 1000000 > ${CGTREE}/cpulimit/cpu.cfs_period_us
echo 100000 > ${CGTREE}/cpulimit/cpu.cfs_quota_us
EOF
# Sub-shell in background
(
# Pid of the current sub-shell
# ($$ would return the pid of the father process)
MY_PID=$BASHPID
# Move current process into the cgroup
sudo sh -c "echo ${MY_PID} > ${CGTREE}/cpulimit/tasks"
# Run the command with calling user id (it inherits the cgroup)
exec "$@"
) &
# Wait for the sub-shell
wait $!
# Exit code of the sub-shell
rc=$?
# Delete the cgroup
sudo rmdir ${CGTREE}/cpulimit
# Exit with the return code of the sub-shell
exit $rc
運行它(在我們獲取當前 shell 的 pid 以在另一個終端中顯示進程層次結構之前):
$ echo $$
112588
$ ./cgrun.sh /bin/sleep 50
這將創建以下進程層次結構:
$ pstree -p 112588
bash(112588)-+-cgrun.sh(113079)---sleep(113086)
停止sleep
過程:
$ kill -STOP 113086
查看 cgroup 以驗證sleep
命令是否正在運行(其 pid 在tasks
文件中)並且 CFS 參數設置正確:
$ ls -l /sys/fs/cgroup/cpu/cpulimit/
total 0
-rw-r--r-- 1 root root 0 nov. 5 22:38 cgroup.clone_children
-rw-r--r-- 1 root root 0 nov. 5 22:38 cgroup.procs
-rw-r--r-- 1 root root 0 nov. 5 22:36 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 nov. 5 22:36 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 nov. 5 22:38 cpu.shares
-r--r--r-- 1 root root 0 nov. 5 22:38 cpu.stat
-rw-r--r-- 1 root root 0 nov. 5 22:38 cpu.uclamp.max
-rw-r--r-- 1 root root 0 nov. 5 22:38 cpu.uclamp.min
-r--r--r-- 1 root root 0 nov. 5 22:38 cpuacct.stat
-rw-r--r-- 1 root root 0 nov. 5 22:38 cpuacct.usage
-r--r--r-- 1 root root 0 nov. 5 22:38 cpuacct.usage_all
-r--r--r-- 1 root root 0 nov. 5 22:38 cpuacct.usage_percpu
-r--r--r-- 1 root root 0 nov. 5 22:38 cpuacct.usage_percpu_sys
-r--r--r-- 1 root root 0 nov. 5 22:38 cpuacct.usage_percpu_user
-r--r--r-- 1 root root 0 nov. 5 22:38 cpuacct.usage_sys
-r--r--r-- 1 root root 0 nov. 5 22:38 cpuacct.usage_user
-rw-r--r-- 1 root root 0 nov. 5 22:38 notify_on_release
-rw-r--r-- 1 root root 0 nov. 5 22:36 tasks
$ cat /sys/fs/cgroup/cpu/cpulimit/tasks
113086 # This is the pid of sleep
$ cat /sys/fs/cgroup/cpu/cpulimit/cpu.cfs_*
1000000
100000
向sleep
進程發送 SIGCONT 信號:
$ kill -CONT 113086
該過程完成並且 cgroup 被銷毀:
$ ls -l /sys/fs/cgroup/cpu/cpulimit
ls: cannot access '/sys/fs/cgroup/cpu/cpulimit': No such file or directory
獲取腳本完成后的退出碼(即啟動命令的退出碼):
$ echo $?
0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.