QProcess, не может создать трубу

Я использую QProcess в слоте таймера с частотой 1 Гц. Процесс предназначен для вызова команды 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 в начале. Это стоило попробовать, я полагаю.

Бесплатное пиво для тех, кто ответит на это 🙂

0

Решение

QProcess происходит от QIODeviceтак что я бы сказал, позвонив близко() должен закрыть дескриптор файла и решить вашу проблему.

1

Другие решения

Я не вижу проблемы, однако одна вещь, которая беспокоит меня, — это возможное дублирование вызова в getMemoryUsage() где он вызывается до завершения предыдущего запуска.

Как насчет реструктуризации этого так, чтобы новый QProcess объект используется внутри getMemoryUsage() (в стеке нет new‘d), а не переменная экземпляра класса верхнего уровня? Это обеспечит очистку (с QProcess объект выходит из области видимости) и позволит избежать любого возможного перекрытия вызовов.

В качестве альтернативы, а не призывая /usr/bin/free как процесс и анализ его вывода, почему бы не прочитать /proc/meminfo непосредственно себя? Это будет много более эффективным.

1

Сначала у меня была такая же ситуация с тобой. Я получил те же результаты.
Я думаю, что QProcess не может правильно обрабатывать открытые каналы.

Тогда вместо QProcess я решил использовать popen () + QFile ().

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.
}
}
1
По вопросам рекламы [email protected]