web-dev-qa-db-ja.com

Ctrl-Cが機能しなかったのはなぜですか?

たった今 Ctrlc 終了するまでに時間がかかるプロセスを停止するために、私のシェルで2回。

^Cは2回エコーされましたが、プロセスは続行されました。

なぜしなかった Ctrlc 通常のようにプロセスを終了しますか?

9
themirror

プロセスは以下を選択できます。

  • を押したときに通常送信されるSIGINT信号を無視する Ctrl-C (シェルのtrap '' INTの場合と同様)または終了しないことを決定する(またはタイムリーに終了できない)独自のハンドラーがある.
  • sIGINTがフォアグラウンドジョブに送信される原因となる文字が別のものであることをターミナルデバイスに通知します(シェルのstty int '^K'など)。
  • 端末デバイスに信号を送信しないように指示します(シェルのstty -isigなど)。

または、システムコールの途中で中断できない場合など、中断できない場合もあります。

Linux(比較的最近のカーネルを使用)では、プロセスが無視しているかどうか、およびhandling SIGINTの出力を確認することで、

$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ:   0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000

SIGINTは2です。上記のSigIgnの2番目のビットは1です。これは、SIGINTが無視されることを意味します。

あなたはそれを自動化することができます:

$ SIG=$(kill -l INT) Perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ && 
    $F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign

現在のintr文字が何であるか、または特定の端末でisigが有効になっているかどうかを確認するには:

$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig

intr文字の上は^Cです(通常、押すと端末(エミュレーター)によって送信される文字) CTRL-C および入力信号は無効になりません。

$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig

intr文字は^Kであり、isig/dev/pts/1に対して無効です)。

完全を期すために、プロセスがSIGINTの受信を停止するために他に2つの方法がある場合がありますが、これは通常見られるものではありません。

に Ctrl+C、SIGINTシグナルは端末のフォアグラウンドプロセスグループのすべてのプロセスに送信されます。通常は、シェルがプロセスグループにプロセスを配置し(シェルjobsにマップされます)、端末デバイスにフォアグラウンドであると伝えます。

これでプロセスは次のことができます:

  • そのプロセスグループを離れます。別のプロセスグループ(フォアグラウンド 1であるプロセスグループ以外のプロセスグループ)に移動すると、SIGINTを受け取りません。 Ctrl-C (SIGTSTP、SIGQUITのような他のキーボード関連の信号も)。ただし、(バックグラウンドプロセスのように)端末デバイスから読み取り(端末デバイスの設定によっては書き込みも可能)しようとした場合は、中断される可能性があります。

    例として:

    Perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'
    

    と中断することができませんでした Ctrl-C。上記のPerlは、親プロセスIDと同じIDを持つプロセスグループに参加しようとします。一般に、そのIDを持つそのようなプロセスグループが存在するという保証はありません。ただし、ここでは、対話型シェルのプロンプトでPerlコマンドが単独で実行される場合、ppidがシェルのプロセスになり、シェルは通常、独自のプロセスグループで起動されます。

    コマンドがまだプロセスグループリーダー(そのフォアグラウンドプロセスグループのリーダー)でない場合は、新しいプロセスグループを開始しても同じ効果があります。

    たとえば、シェルによっては、

    $ ps -j >&2 | Perl -MPOSIX -e 'setpgid(0,0) or die "$!"; sleep 10'
      PID  PGID   SID TTY          TIME CMD
    21435 21435 21435 pts/12   00:00:00 zsh
    21441 21441 21435 pts/12   00:00:00 ps
    21442 21441 21435 pts/12   00:00:00 Perl
    

    同じ効果があります。 psPerlはフォアグラウンドプロセスグループで開始されますが、ほとんどのシェルでは、psがそのグループのリーダーになります(ps上記の出力では、psPerlの両方のpgidがpsのpidであるため、Perlは独自のプロセスグループを開始できます。

  • または、フォアグラウンドプロセスグループを変更することもできます。基本的に、ttyデバイスにSIGINTを他のプロセスグループに送信するように指示します。 Ctrl+C

    Perl -MPOSIX -e 'tcsetpgrp(0、getppid)またはdie $ !;寝る5 '

    そこで、Perlは同じプロセスグループに残りますが、代わりに、フォアグラウンドプロセスグループは、その親プロセスIDと同じIDのグループであることを端末デバイスに伝えています(上記の注を参照)。

13