割り当てのためにシェル パイプの複製に取り組んでいます。パイプラインはすべて機能していましたが (それ以降、パイプライン コードを変更していないため、機能することがわかっています)、パイプラインのあるステップで実行に失敗した場合は、パイプラインを終了する必要がありました。そのコードを実装しているある時点で、パイプラインが予期しない動作を示し始めました。
長さ 2 のパイプラインは正しく機能します。長さが 2 を超えるパイプラインは、次のように失敗します。
- パイプラインの最初のコマンドが実行されます
- その直後 (多くの場合、最初のコマンドの実行が終了する前) に、パイプラインの最後のコマンドが終了します。
- 2 番目のコマンドがハングし、明らかに最初のコマンドから入力を受け取っていません。
以下は、waitpid を使用するセクション コードです (デバッグ コードを除く)。
for (int i = 0 ; i < num_cmds ; i++) {
if (waitpid(cmd_pids[i], &cmd_status[i], NULL) != cmd_pids[i]) {
printf("Error waiting for command %s\n", cmds[i]);
perror("Error");
}
if ((cmd_status[i] > 0) && (cmd_status[i-1] == 0)) {
killPipeline(SIGINT); //Kill pipeline; something failed
}
fflush(logfp);
}
ここで、waitpid セクションが原因であると私が考える理由の核心は次のとおりです。割り当てが要求するいくつかの奇妙な制御フローのため、cmd_status の値を -2 に初期化すると便利であることがわかりました。ロギング関数は、子プロセスの戻りステータスをログに出力します。ファイルには、2 番目の関数の終了ステータスが -2 であることが示されています。これは、もちろん、プログラムで存在ステータスを設定していないことを意味します。パイプラインは、これらのプログラムが実行されるのをまったく待っていないようです。
すなわち
入力 "ls | grep パイプ | wc"
出力:
You entered : list of pipe commands ls | grep pipe | wc
Creating process ls
Creating process grep pipe
Creating process wc
Waiting for command ls
0 0 0 //wc received no input, but somehow an EOF
Command ls finished
Waiting for command grep
^C //Terminate grep because it's waiting for input from a terminated process
Error waiting for command grep
Error: Interrupted system call
Command grep finished
Waiting for command wc
Command wc finished