sleep(1) の最中に Ctrl+T を押してビビった話

2022/08/21に公開

TL;DR

BSD 系のシステムで Ctrl+T を押下するとフォアグラウンドプロセスグループの状態が表示されます。

% uname
FreeBSD
% sleep 3
load: 0.25  cmd: sleep 4097 [nanslp] 1.77r 0.00u 0.00s 0% 2060k
mi_switch+0xc2 sleepq_catch_signals+0x2e6 sleepq_timedwait_sig+0x12 _sleep+0x1d1 kern_clock_nanosleep+0x1c1 sys_nanosleep+0x3b amd64_syscall+0x10c fast_syscall_common+0xf8 
sleep: about 1 second(s) left out of the original 3
% 

FreeBSD の sleep(1)

FreeBSD の sleep(1) に SIGINFO を投げてあげると面白い挙動をするようです。

If the sleep command receives a signal, it takes the standard action. When the SIGINFO signal is received, the estimate of the amount of seconds left to sleep is printed on the standard output.

やってみましょう。

sleep(1) に SIGINFO を投げてみる
% uname -mrsv
FreeBSD 13.1-RELEASE-p1 FreeBSD 13.1-RELEASE-p1 GENERIC amd64
% sleep 20 &
[1] 3800
% kill -INFO 3800
sleep: about 13 second(s) left out of the original 20
% kill -INFO 3800
sleep: about 10 second(s) left out of the original 20
% kill -INFO 3800
sleep: about 6 second(s) left out of the original 20
% kill -INFO 3800
sleep: about 3 second(s) left out of the original 20
% kill -INFO 3800
sleep: about 2 second(s) left out of the original 20
% kill -INFO 3800
sleep: about 1 second(s) left out of the original 20
% kill -INFO 3800
sleep: about 0 second(s) left out of the original 20
% kill -INFO 3800
3800: No such process
[1]    Done                          sleep 20
% 

うん、たしかに報告してくれるようです。

NetBSD や OpenBSD の実装でも試してみたところ、NetBSD のそれが同様の挙動を示しました。

SIGINFO とは

シグナル SIGINFO は BSD 拡張のシグナルのひとつで、キーボードからの状態要求 (status request from keyboard) を表します。 生起したときのデフォルト動作は無視です。 このシグナルは Linux に存在しないようです[1]

シグナル SIGINFO は (stty(1) などによってキー割り付けが変更されていなければ) Ctrl+T を押下することで生起させることができます。 ここで生起されたシグナルはその端末のフォアグラウンドプロセスグループに配送されます。 さらに、フォアグラウンドプロセスグループの状態を表示します。

実際に押してみる

いろいろな BSD で uname, cat, ^T, ^D, sleep 3, ^T を入力してみます。

FreeBSD
% uname 
FreeBSD
% cat
load: 0.15  cmd: cat 4233 [ttyin] 0.65r 0.00u 0.00s 0% 2096k
mi_switch+0xc2 sleepq_catch_signals+0x2e6 sleepq_wait_sig+0x9 _cv_wait_sig+0xec tty_wait+0x1c ttydisc_read+0x2cc ttydev_read+0x56 devfs_read_f+0xd5 dofileread+0x81 sys_read+0xbc amd64_syscall+0x10c fast_syscall_common+0xf8 
% sleep 3
load: 0.13  cmd: sleep 4243 [nanslp] 0.37r 0.00u 0.00s 0% 2060k
mi_switch+0xc2 sleepq_catch_signals+0x2e6 sleepq_timedwait_sig+0x12 _sleep+0x1d1 kern_clock_nanosleep+0x1c1 sys_nanosleep+0x3b amd64_syscall+0x10c fast_syscall_common+0xf8 
sleep: about 2 second(s) left out of the original 3
% 
OpenBSD
$ uname
OpenBSD
$ cat
load: 0.57  cmd: cat 58626 [ttyin] 0.00u 0.00s 0% 55k
$ sleep 3
load: 0.53  cmd: sleep 94438 [nanoslp] 0.00u 0.00s 0% 24k
$ 
NetBSD
$ uname
NetBSD
$ cat
[ 218.3727855] load: 0.03  cmd: cat 492 [ttyraw] 0.00u 0.00s 0% 1092k
$ sleep 3
[ 225.5874919] load: 0.02  cmd: sleep 45 [nanoslp] 0.00u 0.00s 0% 1208k
sleep: Between 2 and 3 seconds left out of the original 3
$ 

おわりに

おわりです。


参考

  • FreeBSD Project. sleep(1). FreeBSD Manual Pages. 2020-12-31. (accessed 2022-08-21).
  • JM Project. Man page of SIGNAL. JM Project. 2020-12-21. (accessed 2022-08-21).
  • W. Richard Stevens; Stephen A. Rago. “10 シグナル”; “18 端末入出力”. 詳解 UNIX プログラミング. 大木敦雄 訳. 第 3 版, 翔泳社, 2014, p.295–358; p.625–662, ISBN978-4-7981-3488-8.
脚注
  1. 一部アーキテクチャにおいては SIGPWR のシノニムになっているようです。 ↩︎

Discussion