QProcess not reading process output
-
Hi all,
I have built a GUI to monitor the results of a test on a Linux machine. On this GUI I have a text browser that I want text to be appended to as the test runs. The program that runs the actual test is a console based application. As it runs, text will output to the Linux terminal. First I declare a new QProcess in the private section of the header file of the class like below.
QProcess *exec = new QProcess(this);
Then here is my code for the rest of the QProcess.
void TestStart::testRunning() { exec->setProcessChannelMode(QProcess::MergedChannels); connect(exec, &QProcess::readyReadStandardOutput, [=] {ui->textBrowser_3->append(exec->readAllStandardOutput());}); connect(exec, &QProcess::readyReadStandardError, [=] {ui->textBrowser_3->append(exec->readAllStandardError());}); QStringList params; params << "google.com"; QString ping = "ping"; QString program = "/home/personal/code/CODE/Example/SigqueueHandling/Program/ReceiveSig"; //exec->start(ping, params); //exec->setWorkingDirectory("/home/personal/code/CODE/Example/SigqueueHandling/Program"); exec->start(program); }
When I uncomment exec->start(ping, params) and comment exec->start(program), the GUI works exactly like it should. That is, the ping command works exactly how I would want my test program to work.
When I uncomment exec->start(program) and comment exec->start(ping, params) and run the GUI, there is no output to my text browser like I expect. When I close the GUI I get the message in the QT Console that QProcess: destroyed while running for program. So I THINK that the program ReceiveSig is at least starting.
I have verified that the directory in program is correct, as when I put that command to the terminal it runs my ReceiveSig program just fine. I am at a loss and any hints would be greatly appreciated. Why is my ReceiveSig program's output not being read by QProcess?
-
Hi all,
I have built a GUI to monitor the results of a test on a Linux machine. On this GUI I have a text browser that I want text to be appended to as the test runs. The program that runs the actual test is a console based application. As it runs, text will output to the Linux terminal. First I declare a new QProcess in the private section of the header file of the class like below.
QProcess *exec = new QProcess(this);
Then here is my code for the rest of the QProcess.
void TestStart::testRunning() { exec->setProcessChannelMode(QProcess::MergedChannels); connect(exec, &QProcess::readyReadStandardOutput, [=] {ui->textBrowser_3->append(exec->readAllStandardOutput());}); connect(exec, &QProcess::readyReadStandardError, [=] {ui->textBrowser_3->append(exec->readAllStandardError());}); QStringList params; params << "google.com"; QString ping = "ping"; QString program = "/home/personal/code/CODE/Example/SigqueueHandling/Program/ReceiveSig"; //exec->start(ping, params); //exec->setWorkingDirectory("/home/personal/code/CODE/Example/SigqueueHandling/Program"); exec->start(program); }
When I uncomment exec->start(ping, params) and comment exec->start(program), the GUI works exactly like it should. That is, the ping command works exactly how I would want my test program to work.
When I uncomment exec->start(program) and comment exec->start(ping, params) and run the GUI, there is no output to my text browser like I expect. When I close the GUI I get the message in the QT Console that QProcess: destroyed while running for program. So I THINK that the program ReceiveSig is at least starting.
I have verified that the directory in program is correct, as when I put that command to the terminal it runs my ReceiveSig program just fine. I am at a loss and any hints would be greatly appreciated. Why is my ReceiveSig program's output not being read by QProcess?
@camtheman99
May depend on howReceiveSig
sends its output, for example it might buffer its output so it doesn't arrive till program end. We don't know. -
@camtheman99
May depend on howReceiveSig
sends its output, for example it might buffer its output so it doesn't arrive till program end. We don't know.ReceiveSig should send out hello world via std::cout every second, while the program is running. After ReceiveSig receives a signal from another program, the text will change to say something else.
I figured the ping command works similar to what I have going on in ReceiveSig, so I expected the same behavior. I should also mention that when I close the GUI without stopping the process, I get the error message in the QT console that the process at /home/personal/code/CODE/Example/SigqueueHandling/Program/ReceiveSig was destroyed while running. This tells me that the process ReceiveSig should be running.
Does std::cout buffer the output somehow?
-
ReceiveSig should send out hello world via std::cout every second, while the program is running. After ReceiveSig receives a signal from another program, the text will change to say something else.
I figured the ping command works similar to what I have going on in ReceiveSig, so I expected the same behavior. I should also mention that when I close the GUI without stopping the process, I get the error message in the QT console that the process at /home/personal/code/CODE/Example/SigqueueHandling/Program/ReceiveSig was destroyed while running. This tells me that the process ReceiveSig should be running.
Does std::cout buffer the output somehow?
@camtheman99 said in QProcess not reading process output:
Does std::cout buffer the output somehow?
It's always buffered ...
See https://en.cppreference.com/w/cpp/io/manip/endl -
Here is the code for ReceiveSig:
//includes below #include <stdlib.h> #include <iostream> #include <unistd.h> #include <stdlib.h> #include <signal.h> void myHandler(int signum, siginfo_t *info, void *extra) { int SigVal = info->si_value.sival_int; if(signum == SIGUSR1) { if(SigVal == 1) { std::cout << "This is signal 1!\n"; } else if(SigVal == 2) { std::cout << "This is signal 2!\n"; } else if(SigVal == 3) { std::cout << "This is signal 3!\n"; } } } int main(){ struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; act.sa_sigaction = &myHandler; sigaction(SIGUSR1, &act, 0); std::cout << "I am right before the while loop\n"; sleep(1); while(1) //this loop repeats forever only to be interrupted by SIGUSR1 { std::cout << "Hello World!\n"; sleep(1); } }
I will reiterate that ReceiveSig works perfectly when I run ./ReceiveSig from the terminal. Should I use something else instead of std::cout? QProcess should work with an infinite loop right? I do not want to waitForFinished, as that will just block the rest of the program forever.
-
Here is the code for ReceiveSig:
//includes below #include <stdlib.h> #include <iostream> #include <unistd.h> #include <stdlib.h> #include <signal.h> void myHandler(int signum, siginfo_t *info, void *extra) { int SigVal = info->si_value.sival_int; if(signum == SIGUSR1) { if(SigVal == 1) { std::cout << "This is signal 1!\n"; } else if(SigVal == 2) { std::cout << "This is signal 2!\n"; } else if(SigVal == 3) { std::cout << "This is signal 3!\n"; } } } int main(){ struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; act.sa_sigaction = &myHandler; sigaction(SIGUSR1, &act, 0); std::cout << "I am right before the while loop\n"; sleep(1); while(1) //this loop repeats forever only to be interrupted by SIGUSR1 { std::cout << "Hello World!\n"; sleep(1); } }
I will reiterate that ReceiveSig works perfectly when I run ./ReceiveSig from the terminal. Should I use something else instead of std::cout? QProcess should work with an infinite loop right? I do not want to waitForFinished, as that will just block the rest of the program forever.
@camtheman99 said in QProcess not reading process output:
Should I use something else instead of std::cout?
Did you actually read my post and the links I poosted?
-
Here is the code for ReceiveSig:
//includes below #include <stdlib.h> #include <iostream> #include <unistd.h> #include <stdlib.h> #include <signal.h> void myHandler(int signum, siginfo_t *info, void *extra) { int SigVal = info->si_value.sival_int; if(signum == SIGUSR1) { if(SigVal == 1) { std::cout << "This is signal 1!\n"; } else if(SigVal == 2) { std::cout << "This is signal 2!\n"; } else if(SigVal == 3) { std::cout << "This is signal 3!\n"; } } } int main(){ struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; act.sa_sigaction = &myHandler; sigaction(SIGUSR1, &act, 0); std::cout << "I am right before the while loop\n"; sleep(1); while(1) //this loop repeats forever only to be interrupted by SIGUSR1 { std::cout << "Hello World!\n"; sleep(1); } }
I will reiterate that ReceiveSig works perfectly when I run ./ReceiveSig from the terminal. Should I use something else instead of std::cout? QProcess should work with an infinite loop right? I do not want to waitForFinished, as that will just block the rest of the program forever.
@camtheman99
The usual behaviour for stdout buffering is: when outputting to terminal line buffered, so sending\n
flushes the buffer, but when outputting to a file or pipe (like when run as a sub-process not connected to a terminal) block buffered, meaning output not flushed until a fair amount has been sent (4k?) or process flushes on exit. Could this describe what you are seeing?UPDATE In any case, why don't you put
endl
s into your client code like @Christian-Ehrlicher says and see if that gives you what you are asking for? -
Hey guys, I updated my code to include std::endl instead of "\n" and it worked how I expected! I had no idea there was such a distinction between the two as I hadn't run into this before. Thank you both for your input.
-
Hey guys, I updated my code to include std::endl instead of "\n" and it worked how I expected! I had no idea there was such a distinction between the two as I hadn't run into this before. Thank you both for your input.
@camtheman99
That is interesting, thanks to @Christian-Ehrlicher.