'QProcess does not signal stdout ready
When I launch xfreerdp process out of shell, it prints INFO messages to stdout and WARN/ERROR messages to stderr, as expected (this is just the default /log-level:info mode).
However, when I launch it via QProcess, the QProcess only signals with readyReadStandardError()
, i.e. allowing me to read WARN/ERROR messages but never signals with readyReadStandardOutput()
. Only when the process finishes (I close the xfreerdp window), the signal is emitted by QProcess and all the stdout is read by me (I have no idea, where was it kept all the way long?)
I have found two topics concerning the problem:
I tried solutions proposed there:
1). I tried to use QIODevice::ReadWrite | QIODevice::Unbuffered
as the third argument of QProcess::start()
. It did not help -- same as it is described by the links.
2). I tried to call QProcess::readAllStandardOutput()
every 100ms using QTimer
. However, when I read this way, the output byte array is always empty (until the process is finished). So again, same as told by by the links, it did not help.
When I launch xfreerdp with QProcess with /log-level:debug
or /log-level:trace
, the problem does not hold. I get signals of stdout being ready. But there are lots and lots of DEBUG/TRACE messages.
I search for a way to solve the problem. But if I don't find it, I have two options: either to use the default /log-level:info
option or /log-level:debug
option. The first one is preferable for me but I am afraid that all that stdout is stuck somewhere and I would get with an overflow of some buffer and the whole thing would crash or it would be like a memory leak (maybe, I will try to explore QProcess source code). The second one is so here, probably, a better option, but the debug mode of xfreerdp is really quite too verbose.
UPDATE with the minimal reproducible example:
Alas, one need a vm to connect to.
If one launches the example (I have checked on Fedora 35 and Fedora 33), one will see that xfreerdp will output the INFO messages only after one will close the xfreerdp window, i.e., only after the process finishes.
//
// main.cpp
// g++ -o main main.cpp -std=c++11 -I/usr/include/qt5 -L/usr/lib64 -lQt5Widgets -lQt5Core
//
#include "QtWidgets/QApplication"
#include "QtCore/QProcess"
int main(int argc, char* argv[])
{
QApplication app{argc, argv};
QProcess p;
QObject::connect(&p, &QProcess::readyReadStandardOutput, [&](){
printf("%s", p.readAllStandardOutput().constData());
});
p.start("xfreerdp", {"/u:user", "/p:123456", "/v:10.38.31.133", "/cert:tofu"});
app.exec();
return 0;
}
I am sorry I was mistaken not to post the minimal reproducible example at once. Maybe, I should close the question and create a new once, so that more people could see it?
Solution 1:[1]
In your program, QProcess
will do like works as entered in the terminal this command :
For seeing the result better I checked open in Terminal in the Run section of Qt Creator:
So I do this in Qt and add some changes to your code:
#include "QtWidgets/QApplication"
#include "QtCore/QProcess"
int main(int argc, char *argv[])
{
QApplication app { argc, argv };
QProcess *p = new QProcess();
QStringList pArgs;
pArgs << "/u:user" << "/p:123456" << "/v:10.38.31.133" << "/cert:tofu";
p->setProgram(QString("xfreerdp"));
p->setArguments(pArgs);
p->start();
QObject::connect(p, &QProcess::readyReadStandardOutput, [&]()
{
// printf("%s", p->readAllStandardOutput().constData());
qDebug() << p->readAllStandardOutput().constData() << Qt::endl;
});
app.exec();
return 0;
}
you should take Arguments to QProcess by using QStringList
.
As I test it takes 15 to 16 seconds delay to show you results but this is my results:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Parisa.H.R |