ターミナルエミュレータがシャットダウンするとシェルもシャットダウンされるのはなぜですか?

ターミナルエミュレータがシャットダウンするとシェルもシャットダウンされるのはなぜですか?

ターミナルエミュレータ(qterminalなど)を起動すると、デフォルトのシェル(bashなど)が起動します。ターミナルを終了すると(xボタンをクリックするかターミナルを終了するなど)、シェルも終了します。シェルはプロセスを残しません。このメカニズムがどのように実装されるかを知りたいです。

最初は、端末がシェルに信号を送信していると疑っていました。そのため、シェルでSIGQUIT、SIGINT、SIGTERM、SIGHUPをキャッチしましたが、どのシグナルも見つかりませんでした。信号以外にはわかりません。

端末とシェルによって異なる場合があり、オペレーティングシステムによって異なります。この状況に関する情報を教えてください。

ベストアンサー1

通常、端末はプロセスに中断信号(SIGHUP)を送信します。また、ターミナルがptyの「基本」側を閉じると、ターミナルに接続されている一部のプロセスも、ターミナルがSIGHUPを送信するか送信しないかにかかわらず、カーネルから自動的にSIGHUPを受け取ります。

カーネルの信号が pty を制御端末とするすべてのプロセスに送信されるわけではありませんが - 具体的には確認しませんが、基本的に SIGINT/SIGQUIT と同じ「フロントエンド pgroup」に特別に渡されるようです。 Ctrl+C/Ctrl+\ から。

シェル自体(たとえば、Bash)には、すでに他のすべてのシェルに追加のSIGHUPを送信するSIGHUPハンドラがあります。背景作業シェルによって管理されます(edを無視disown)。たとえば、sleep 1h &a は SIGHUP 自体を受信したため、終了しようとすると Bash によって SIGHUP されます。

たとえば、端末をきれいに閉じる場合:

$ sudo strace -p ${pid_of_bash}
strace: Process 102874 attached
pselect6(1, [0], NULL, NULL, NULL, {sigmask=[], sigsetsize=8}) = ? ERESTARTNOHAND
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=87390, si_uid=1000} ---
--- SIGCONT {si_signo=SIGCONT, si_code=SI_KERNEL} ---
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
--- SIGHUP {si_signo=SIGHUP, si_code=SI_KERNEL} ---
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
[...]

close(ptmx_fd)デバッガを使用して端末プロセスで実行する場合:

$ sudo strace -p ${pid_of_bash}
pselect6(1, [0], NULL, NULL, NULL, {sigmask=[], sigsetsize=8}) = 1 (in [0])
--- SIGHUP {si_signo=SIGHUP, si_code=SI_KERNEL} ---
--- SIGCONT {si_signo=SIGCONT, si_code=SI_KERNEL} ---
rt_sigreturn({mask=[]})                 = 1
read(0, "", 1)                          = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
ioctl(2, TCXONC, TCOON)                 = -1 EIO (Input/output error)
write(2, "\33[?2004l\r", 9)             = -1 EIO (Input/output error)

最後に、ptyが閉じられると、シェル(または他のフォアグラウンドプログラム)は、ptyから読み取ろうとするとEOF(つまり0を返す)を受け取り、read()Ctrl + Dを押すのと同じように処理します。これは一般的にプログラムを終了するために当然です。できるEOFを無視する(SIGHUPを無視することにしたときに、特定のプログラムがこの状況で無限ループに入るのを見たことがあります)。そしてEOF)。

シェルはEOFで終了する可能性が高いです。今後カスタムSIGHUPハンドラに到達します。たとえば、trap ... SIGHUPGNOME端末の下のBashで(呼び出しなし)結果を再現できます。しかし、Bash に EOF で終了しないようにさらに指示すると、カスタムIGNOREEOF=1SIGHUP トラップが呼び出されます。

カスタムトラップも発生書くBashのデフォルトの「SIGHUP終了」動作です。だからBashにEOFを無視するように言うときそしてトラップSIGHUP、実際には存在しないttyにプロンプ​​トを印刷しようとし続けます。 「strace」出力は、通常のPROMPT_COMMANDフックをすべて呼び出し、stdoutにプロンプ​​トを書き込もうとし、EIOをインポートしてから書き込もうとすることを示しています。 EIOから得られたエラーメッセージstderrそれ、その後、十分だと判断して終了します。

おすすめ記事