进程,无法创建管道

QProcess, Cannot Create Pipe

本文关键字:创建 管道 进程      更新时间:2023-10-16

我在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