forkpty() で始まる Bash シェルは、SIGINT を無視する子プロセスを生成します。 SIGINTが無視されないようにする理由と方法は何ですか?

forkpty() で始まる Bash シェルは、SIGINT を無視する子プロセスを生成します。 SIGINTが無視されないようにする理由と方法は何ですか?

bashシェルを実行するためにforkptyを使用するCプログラムがあります。私はこのシェルによって起動されたプログラムが起動時にSIGINTを無視することを発見しました。そのため、Ctrl-Cをシェルに送信したときに決して閉じられませんでした。

例:

int masterFd;
char* args[] = {"/bin/bash", "-i", NULL };
int procId = forkpty(&masterFd, NULL, NULL,  NULL);
if( procId == 0 ){
  execve( args[0], args, NULL);
}
else {
   // Simple code that reads from standard in and writes to masterFd.  
   // I also register for Ctrl-C and write it to masterFd if caught
}

他の制御文字は、ctrl-D、ctrl-?を介して動作するようです。ところで、新しいbashシェルで起動されたプロセスの状態を見るたびに、SIGINTがブロックされているように見えます。

MyShell:# sleep 1000

StandardTerm:#  ps -ef | grep sleep
root    26611  19278  0  17:44  pts/1   00:00:00 sleep 1000
root    26613  32376  0  17:44  pts/1   00:00:00 grep sleep

StandardTerm:# grep Sig proc/26611/status
SigQ:    0/256428
SigPnd:  0000000000000000
SigBlk:  0000000000000000
SigIgn:  0000000000010006   <- THE 6 IS THE PROBLEM
SigCgt:  0000000180000000

SigIgnにはビット2が設定されており、これは2(SIGINT)が無視されることを意味します。同じことを行いますが、標準端末でスリープモードを実行すると(または大容量ファイルなどを処理する場合)、ビットはクリアされます。 pty bashを起動してSIGINTを無視する孫を作成させる場合はどうすればよいですか?

また、プロセスにSIGINT信号を送ると

StandardTerm:# kill -2 26611

何もしません。奇妙なことは、同じコマンドをbashシェルに送信すると、bashシェルがSIGINTを無視しないために機能することです。

答え1

おそらく、次のことを行う必要があります。

stty sane

私は気づいたforkpty() manページにtermios設定をコピーします。*termp新しく開かれた pty に対するものですが、それを処理する方法を指定しません。NULL 以外の唯一の引数はforkpty()pty マスター fd です。私の考えでは、完全に空のtermios構造で終わると思いますが、これはあまり役に立ちません。あまり問題にならないでしょう。独自の端末操作をすべて処理するbash必要があるため、とにかく基本的にすべての基本文字を解釈します。readline()

これは有益なブロック引用符から来ています。記事このトピックについて:

stty-Fオプションは、他のプログラムが端末で何をしているかを確認するのに役立ちます。ttyシェルで実行すると、そのシェルのターミナルデバイスパスが印刷されます。/dev/pts/N(少なくともLinuxでは一般的な形式)。別のシェルで実行して、stty -a -F /dev/pts/N最初のシェルの端末がどのように構成されているかを確認できます。その後、最初のシェルでプログラムを実行し、stty2番目のシェルで注文を繰り返して、どの設定が設定されているかを確認できます。たとえば、stty -F /dev/pts/10今実行するとbashそのptyを通して誰かと話すとき)gnome-terminal、理解します:

    $ stty -F /dev/pts/10
      speed 38400 baud; line = 0;
      eol = M-^?; eol2 = M-^?; swtch = M-^?; lnext = <undef>; min = 1; time = 0;
     -icrnl iutf8
     -icanon -echo

bash/readlineこれにより、無効になっていることを確認できます。CR→LF翻訳入力( icrnl)、障害を負うcanonicalモードとechoしかし、UTF-8モードが有効bashutf-8ロケールが検出されたため)sttyそのシェルから直接実行すると、若干異なる内容が表示されます。

     $ stty
       speed 38400 baud; line = 0;
       eol = M-^?; eol2 = M-^?; swtch = M-^?;
       iutf8

bash独自の設定を維持するtermiosためです。(のためreadlineの)を実行してプログラムを実行したときの設定がプロンプトに入力したときの設定と異なるように、実行中のプログラムの設定を保存して復元しますbash

答え2

この結果は、お客様の質問に記載されているコードブロックによるものではありません。全体設定の他の部分には他のものが必要です。

説明する使用シナリオを考えると、最も可能性の高い理由は、実際にコードのどこかにSIGINT無視を設定したためです。今後フォークまたは今後フォークティ子供を実行します。

これはあなたが説明する結果を生み出します。なぜなら、あなたのforkpty'edはbash -iSIGINTが無視された設定を継承し、独自の内部目的のために別の状態に設定するからです(SIGINTを無視しません)。また、継承された状態にリセットされます。生成されるすべてのコマンドの状態を無視します。

これは Bash の動作に関するドキュメントです。 Bashのマニュアルページの「コマンド実行環境」の章、特に次の段落を参照してください。

組み込み関数やシェル関数ではなく単純なコマンドを実行したい場合は、次のように構成された別の実行環境で呼び出されます。 [...]

[...]

oシェルが捕捉したトラップは、シェルの親から継承された値にリセットされ、シェルが無視したトラップは無視されます。

ファタイ

関連情報