gpt4 book ai didi

c++ - 如何确保 popen()ed 进程在退出时运行析构函数?

转载 作者:行者123 更新时间:2023-11-30 03:06:07 31 4
gpt4 key购买 nike

如果我有一个管道来运行一些命令,管道命令需要做一些清理,但是,如果启动管道的进程有错误,管道命令不会清理。在这种情况下,管道命令是否获得 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 发生的 volatile 全局变量,并在主线代码中将其作为错误条件进行测试。

一些其他评论:

  • 在处理popenpclosewrite 等C 函数时,您应该检查返回状态。您在调用 popenpclose 时没有这样做,至少在示例代码中没有这样做。
  • 为什么 class Cleanup 不对称?构造函数接收一个已经构造的 FILE 指针,但析构函数通过 pclose 销毁它。 IMO 如果构造函数调用 popen 会更好,将命令字符串作为构造函数的参数。

附录
也许比为 SIGPIPE 创建一个设置一些全局变量的处理程序更好的方法是将 SIGPIPE 的处理程序设置为忽略,然后检查您对管道的写入是否存在 EPIPE 错误。

关于c++ - 如何确保 popen()ed 进程在退出时运行析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6973558/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com