进程,无法创建管道
QProcess, Cannot Create Pipe
我在1 Hz的计时器槽中运行一个QProcess。该过程旨在调用Linux命令并解析其输出。
问题是这样的:程序运行了大约20分钟后,我得到了这个错误:
QProcessPrivate::createPipe: Cannot create pipe 0x104c0a8: Too many open files
QSocketNotifier: Invalid socket specified
理想情况下,该程序将在系统的整个正常运行时间内运行,可能是几天或几周。
我想通过阅读示例,我对过程控制一直很小心,但也许我遗漏了一些东西。我使用了Qt网站上的示例,它们使用了我编写的相同代码,但这些代码是为单一用途而设计的,而不是成千上万的。下面是一个最小的例子:
class UsageStatistics : public QObject {
Q_OBJECT
public:
UsageStatistics() : process(new QProcess) {
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(getMemoryUsage()));
timer->start(1000); // one second
}
virtual ~UsageStatistics() {}
public slots:
void getMemoryUsage() {
process->start("/usr/bin/free");
if (!process->waitForFinished()) {
// error processing
}
QByteArray result = process->realAll();
// parse result
// edit, I added these
process->closeReadChannel(QProcess::StandardOutput);
process->closeReadChannel(QProcess::StandardError);
process->closeWriteChannel();
process->close();
}
}
我还尝试在函数结束时手动deleting
进程指针,然后在开始时new
。我想这值得一试。
回答这个问题的人有免费啤酒:)
QProcess
来源于QIODevice
,所以我想说调用close()应该关闭文件句柄并解决您的问题。
我看不出这个问题,但是我担心的一件事是getMemoryUsage()
中可能的调用重叠,在以前的运行完成之前调用。
如何重组这使得新的QProcess
对象在getMemoryUsage()
(在堆栈上,而不是new
'd)中使用,而不是作为顶级类的实例变量?这将确保清理(QProcess
对象超出作用域),并避免任何可能的调用重叠。
或者,与其调用/usr/bin/free
作为进程并解析其输出,为什么不自己直接读取/proc/meminfo
呢?这将使更有效率。
首先我和你有同样的情况。我得到了相同的结果。我认为QProcess不能正确处理打开的管道
然后,我决定使用popen() + QFile()来代替QProcess。
class UsageStatistics : public QObject {
Q_OBJECT
public:
UsageStatistics(){
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(getMemoryUsage()));
timer->start(1000); // one second
}
virtual ~UsageStatistics() {}
private:
QFile freePipe;
FILE *in;
public slots:
void getMemoryUsage() {
if(!(in = popen("/usr/bin/free", "r"))){
qDebug() << "UsageStatistics::getMemoryUsage() <<" << "Can not execute free command.";
return;
}
freePipe.open(in, QIODevice::ReadOnly);
connect(&freePipe, SIGNAL(readyRead()), this, SLOT(parseResult()) );
// OR waitForReadyRead() and parse here.
}
void parseResult(){
// Parse your stuff
freePipe.close();
pclose(in); // You can also use exit code by diving by 256.
}
}
这是因为您的应用程序希望使用的资源超过了系统范围的资源限制所允许的数量。如果你有一个巨大的应用程序,你可以使用[2]中指定的命令来解决它,但它可能是由编程错误引起的。
:
我刚刚解决了一个类似的问题。我使用一个QThread来记录QProcesses的退出代码。QThread使用curl连接FTP服务器上传日志。由于我正在测试软件,我没有连接FTP服务器和curl_easy_perform
显然等待连接。因此,我的资源限制达到了,我得到了这个错误。过了一段时间,我的程序开始抱怨,这是找出问题所在的主要指标。
[..]
QProcessPrivate::createPipe: Cannot create pipe 0x7fbda8002f28: Too many open files
QProcessPrivate::createPipe: Cannot create pipe 0x7fbdb0003128: Too many open files
QProcessPrivate::createPipe: Cannot create pipe 0x7fbdb4003128: Too many open files
QProcessPrivate::createPipe: Cannot create pipe 0x7fbdb4003128: Too many open files
[...]
curl_easy_perform() failed for curl_easy_perform() failed for disk.log
[...]
在这个错误发生后,我通过将机器连接到FTP服务器进行了测试。这解决了我的问题。
:
[1] https://linux.die.net/man/3/ulimit
[2] https://ss64.com/bash/ulimit.html
[3] https://bbs.archlinux.org/viewtopic.php?id=234915
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 使用std::multimap迭代器创建std::list
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 如何创建函数管道,以便函数一个接一个地运行?
- GLib-ERROR:为GWakeup创建管道:打开的文件太多
- gStreamer 将元素添加到通过 gst_parse_launch 创建的管道中
- 使用提升连接已创建的命名管道
- 创建名为管道错误
- 创建一个可以在没有实验的情况下变形的管道::任何
- 用管道在C++中创建调度队列/线程处理程序:FIFO溢出
- 我应该使用 DeviceContext 函数在管道中循环输入还是通过创建来输入
- 从管道中创建(或传递)字符串
- 在使用pthread_create创建的线程之间读取和写入管道时,是否需要关闭 fds
- 为 Intranet 主机创建C++命名管道
- 尝试创建命名管道失败并显示ERROR_IS_SUBSTED
- 进程,无法创建管道
- 管道ppm文件到ffmpeg在c++中创建电影
- 无法使用cefclient创建管道
- 命名管道错误:无法创建带有错误0x0000007b的命名管道
- 如何在c++中创建管道