「130で終了するのがSIGINTで死ぬのとは違うのはなぜですか?」

「130で終了するのがSIGINTで死ぬのとは違うのはなぜですか?」

ステファン・チャジェラスの返信https://unix.stackexchange.com/a/230568

理想的には、SIGINTで死亡したことを親に報告したいと思います(したがって、他のbashスクリプトの場合、そのbashスクリプトも中断されます)。130を終了することは、SIGINTで死ぬこととは異なります。(一部のシェルは$?を両方の場合に同じ値に設定しますが)通常、SIGINTを介して死を報告するために使用されます(SIGINTが2のシステムではこれが最も多いです)。

しかし、これはbash、ksh93、またはFreeBSD shでは機能しません。 SIGINT は 130 終了ステータスを死亡として扱いません。そして親スクリプトはそこで終わりません。

  1. 「130に出るのはSIGINTで死ぬのとは違う」という点で違いは何ですか?
  2. なぜ「bash、ksh93、またはFreeBSD shではこれは機能しません。

Bashのマニュアルから:

致命的な信号番号Nが原因でコマンドが終了すると、Bashは128 + Nの値を終了状態として使用します。

SIGINTのシグナル番号は2なので、SIGINTで終了するコマンドの終了状態は130です。だから私の考えでは、130番出口を実行するのはSIGINTを使った死と同じで、130番出口の状態は死信号と見なされます。

ありがとうございます。

ベストアンサー1

$?最後のコマンドがSIGINTで終了した後に表示される130(128 + SIGINT)は、一部のシェルによって発生します(たとえば、bash他のシェルは異なる表現を使用します(例:ksh93の256+signum、yash signumの128+256+ 、/in sigint、または他のテキスト)。sigquit+corercesプロセスの終了時にデフォルトの終了コードは何ですか?もっと学ぶ。

プロセスは子を待って状態を照会できます。

  • 停止した場合(どの信号を使用するか)
  • 復元された場合
  • 死んだら(どんな信号でも)
  • もしあれば閉じ込められた(のためdプロセス)
  • 倒れると核兵器
  • システムコールを介して正常に終了するかどうか_exit()(どの終了コードを使用するか)

そのために、、、、(廃止予定の、参照)のいずれかを使用するか、wait()SIGCHLDwaitpid()システムwaitid()コールwait3()wait4()ハンドラを使用します。

これらのシステムコールは上記のすべての情報を返します。 (waitid()一部のシステムを除いて、正常に終了する子プロセスに渡された数のうち、最も低い8ビットのみを_exit()使用できます。)

ただしbash、(Bourneやcshなどのほとんどのシェルは)すべての情報を8桁の数字で囲みます$?$?正常に終了したプロセスの終了コードのうち最も低い8桁、終了または中断またはトラップされている場合は128+signum)。は使用できません)。明らかに、いくつかの情報がありません。具体的には、SIGINTによって$?プロセスが実行されたのか、終了されたのかを自分で知ることはできません。_exit(130)

bashプロセスがいつ終了するかを明確に知ることができます。たとえば、バックグラウンドプロセスが終了すると、次のようになります。

[1]+  Interrupt               sleep 20

ただし、$?SIGINTによって終了されたか呼び出されたかを知るのに十分な情報は提供されません_exit(130)

ほとんどのシェルはこの変換を実行するため、アプリケーションはシグナルを介してシャットダウンを報告する_exit(number_greater_than_127)以外は何もしません。

それにもかかわらず、プロセスが実行されると、_exit(130)それを待つプロセスは信号によって終了するのではなく、プロセスが正常に終了したことを検出します。 Cでは、WIFEXITED()次を返します。本物WIFSIGNALED()falseを返します。

bash$?プロセス自体は、SIGINTによってプロセスが終了したとは思わない(SIGINTによって終了したのと同じ値を持つことができると考えても)。

したがって、これはSIGINTの特別な処理をトリガしませんbash。スクリプト内でbash現在スクリプトで実行されているコマンドはすべてSIGINTを受け取ります^C(すべて同じプロセスグループにあるため)。

bash待機中のコマンドもSIGINTで終了した場合にのみSIGINTを受信すると終了します(たとえば、スクリプトでvi以下を実行し、^ Cを使用して一部のコンテンツを引き起こしたり終了させたりしないvi操作を中断するというアイデアです。終了/後で戻るless時スクリプトは消えません)。viless

コマンドがSIGINTハンドラで実行をbash待っている場合、そのSIGINTは終了しません(子プロセスが中断されたと信じていないため、中断されたとは思いません)。_exit(130)bash

だから報告したいときSIGINTによる死亡、それハンドラからその信号を受信した後、実際に追加の処理を実行しても実際には中断されます。、を実行してはいけませんが、実際に_exit(130)SIGINTで自殺する必要があります(SIGINTのデフォルトハンドラを復元した後)。シェルでは次のようになります。

trap '
  extra processing
  trap - INT # restore SIGINT handler
  kill -s INT "$$" # report to the parent that we have indeed been
                   # interrupted
  ' INT

おすすめ記事