簡體   English   中英

如何確保popen()進程在退出時運行析構函數?

[英]How to ensure popen()ed process runs destructors on exit?

如果我有運行命令的管道,則管道命令需要進行一些清理,但是,如果啟動管道的進程出現錯誤,則管道命令不會清理。 在這種情況下,管道命令是否獲取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);
}

在信號處理程序中引發異常是一個非常糟糕的主意。 信號處理程序必須是異步安全的。 更糟糕的是,信號處理程序在其中運行,其執行線程與主線代碼本質上是不同的線程。 最好使您的信號處理程序小而原始。 例如,使SIGPIPE處理程序設置一些易失的全局變量,該變量指示SIGPIPE發生,並在主線代碼中將其測試為錯誤情況。

其他一些評論:

  • 處理諸如popenpclosewrite等C函數時,應檢查返回狀態。 調用popenpclose並沒有這樣做,至少在示例代碼中沒有這樣做。
  • 為什么在class Cleanup不對稱? 構造函數接收一個已經構造的FILE指針,但是析構函數通過pclose銷毀它。 IMO最好是構造函數調用popen ,將命令字符串作為構造函數的參數。

附錄
也許比為SIGPIPE創建一個設置全局變量的處理程序更好,是將SIGPIPE的處理程序設置為忽略,然后從對管道的寫入中檢查EPIPE錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM