[英]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發生,並在主線代碼中將其測試為錯誤情況。
其他一些評論:
popen
, pclose
和write
等C函數時,應檢查返回狀態。 調用popen
或pclose
並沒有這樣做,至少在示例代碼中沒有這樣做。 class Cleanup
不對稱? 構造函數接收一個已經構造的FILE
指針,但是析構函數通過pclose
銷毀它。 IMO最好是構造函數調用popen
,將命令字符串作為構造函數的參數。 附錄
也許比為SIGPIPE創建一個設置全局變量的處理程序更好,是將SIGPIPE的處理程序設置為忽略,然后從對管道的寫入中檢查EPIPE錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.