1

コマンドを実行するためのパイプがある場合、パイプされたコマンドはクリーンアップを行う必要がありますが、パイプを開始したプロセスにエラーがある場合、パイプされたコマンドはクリーンアップされません。この場合、パイプされたコマンドは SIGPIPE を取得していますか? cleanupPipe デストラクタが常に実行されるようにするにはどうすればよいですか? errorOccurred 例外がスローされると、cleanupPipe デストラクタが実行されていないことがわかります。例外をスローするように SIGPIPE ハンドラーを設定しているので、結果が SIGPIPE の場合、SIGPIPE の結果として例外がスローされ、スタックが巻き戻されたときに、デストラクタが実行されることを期待します。

void
testCase() {
  class cleanup {
  public:
    cleanup(FILE *pipe)
      : _pipe(pipe) {
    }
    ~cleanup() {
      ::pclose(_pipe);
    }

  private:
    FILE *_pipe;

  };

  string cmd("runMyCommandImplementationHere argsHere");
  FILE *pipePtr = ::popen(cmd, "w");
  cleanup cleanUpPipe(pipePtr);

  // Normally, write data to pipe until process in pipe gets all the data it
  // needs and exits gracefully.
  for (;;) {
    if (someErrorOccured()) {
      // When this error occurs, we want to ensure cleanupPipe is run in piped
      // process.
      throw errorOccurred(status);
    }
    if (finishedWritingData()) {
      break;
    }
    writeSomeDataToPipe(pipePtr);
  }
}

void
myCommandImplementationHere() {
  class cleaupPipe {
  public:
    cleanupPipe(const string &filename)
      : _filename(filename) {
    }
    ~cleanupPipe() {
      ::unlink(_filename.c_str());
    }

  private:
    string _filename;

  };

  string file("/tmp/fileToCleanUp");
  cleanupPipe cleanup(file);

  doSomeWorkOnFileWhileReadingPipeTillDone(file);
}
4

1 に答える 1

3

シグナル ハンドラで例外をスローすることは、非常に悪い考えです。シグナル ハンドラーは、非同期セーフである必要があります。さらに悪いことに、シグナル ハンドラは、メインライン コードとは本質的に異なる実行スレッドで実行されます。シグナル ハンドラーを小さく、非常に基本的なものにしておくのが最善です。たとえば、SIGPIPE ハンドラーで、SIGPIPE が発生したことを示す揮発性のグローバル変数を設定し、それをメインライン コードのエラー条件としてテストします。

その他のコメント:

  • popenpclose、などの C 関数を扱う場合は、戻りステータスを確認する必要がありwriteます。popenまたはへの呼び出しpcloseでは、少なくともサンプル コードではそうしていません。
  • の非対称性はなぜclass Cleanupですか? コンストラクターは既に構築されたFILEポインターを受け取りますが、デストラクターはそれを 経由で破棄しpcloseます。popenIMOコンストラクターがを呼び出し、コマンド文字列をコンストラクターへの引数として使用する方が良いでしょう。

補遺
おそらく、グローバル変数を設定する SIGPIPE のハンドラーを作成するよりも、SIGPIPE のハンドラーを無視するように設定し、パイプへの書き込みから EPIPE エラーをチェックする方が良いでしょう。

于 2011-08-07T15:23:56.303 に答える