QProcess finish signal not emitted.
-
Hello, I have been struggling for a few days trying to make my Qt application to execute another application by using a QProcess and waiting for its completion
by connecting to the finish signal.I have tried this way:
connect(&proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[=](int exitCode, QProcess::ExitStatus exitStatus)
{
std::cout<<" Received"<<std::endl;
this->handle_finished(exitCode);
});and I have also tried :
QObject::connect(&proc, SIGNAL(finished(int)), this, SLOT(handle_finished(int)),Qt::QueuedConnection);
If use the second option, it never ever receive the signal, even if the process is closed or terminated by my main application.
If I use the first method, I get a signal, but as a directConnect handled signal, and only if I close the QProccess from my own QtApplication.
In neither case I receive the signal if the application closes by itself (or is closed by the operating system). I have tried literally a dozen different applications an all have this same issue (so I know the problem is not on the application I am starting).
I am running an Ubuntu 20.04 desktop with Qt 5.12.8
Can anyone point me some hints on how can I figure what is not working?
I forgot to say, I do these connections in a thread that is not the main thread (is the same one that creates the QProcess).
-
Hi, I am replying to myself to add something I discovered. The problem is not related to the signals. The QProccess state is still stuck in Starting. The proccess already started, had run for several seconds and has finished but the ProcessState is still suck in starting.
Has anyone seen something like that?
-
@TiagoSD said in QProcess finish signal not emitted.:
I forgot to say, I do these connections in a thread that is not the main thread (is the same one that creates the QProcess).
Could you clarify this sentence: the connects, signals, slots and the
QProcess
are all in the non-UI thread? Or, theQProcess
is in the main thread, but the connections/signals/slots are not? -
Hi and welcome to devnet,
What exactly are you executing ?
Can you show the full code related to QProcess ? -
@SGaist said in QProcess finish signal not emitted.:
Hi and welcome to devnet,
What exactly are you executing ?
Can you show the full code related to QProcess ?Basically this:
procc = new QProcess();connect(procc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [=](int exitCode, QProcess::ExitStatus exitStatus) { std::cout<<"DEBUG"<<std::endl; this->handle_finished(exitCode); });
procc->start(appname.c_str());
Now, I just discovered something.. weird. If I call waitForStarted().. it goes immediately into running state (otherwise it stays stuck in starting.. forever even after the process ends).
but it does never reach not_running state, unless I waitForFinished()
It seems the problem is not in the signals but in Qt keeping track of the state correctly. As far as I understood the documentation I should be able to start the process. NOT call waitForFinished() and expect the state of the QProccess to still be updated to the correct values. Am I wrong?
-
What application are you trying to start that has issues ?
-
Are you blocking the eventloop somehow?
-
@SGaist
You know more than I, but I don't think the process he runs is at issue. I believe it itself runs fine. The issue, I think, lies in the use of threads, or where the event loop is allowed to run so the status is updated, signals are delivered, etc. ThewaitFor...()
spins its own loop and works. No? -
@SGaist I have tried even a helloworld program. Simple basic std::cout<<"Hello World" <<std::endl; return 0 at main. My objective is to tun another application that I made with Qt, but when I started to face the problem I decided to try with an application as simple as possible to help detect what is wrong.
@Christian-Ehrlicher nope. The events from my interface work correctly, all clicks, released etc events are handled perfectly even while the process that I started is running, so I figure the event Loop must be working.
I can reproduce the same issue by creating the minimal QtWidget program with QtCreator and with the following main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QProcess>
#include <thread>
#include <iostream>int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();std::thread* ptr = new std::thread([]() { std::this_thread::sleep_for(std::chrono::seconds(5)); QProcess proc; proc.start("/tmp/batata"); while(proc.state()!=QProcess::NotRunning) std::cout<<" waiting:"<<proc.state()<<std::endl; std::cout<<"DONE"<<std::endl; }) ; auto execresult= a.exec(); ptr->join(); delete ptr; return execresult;
}
the process state stays stuck at 1.. forever.. the program at /tmp/batata just writes linesin a file for 10 seconds and then exits... but even after it finishes the state is stuck at 1.
I must be missing something here. Even by this simple example the QProcess is created and started quite after the QApplication exec starts (the sleep is there to ensure it).
-
@TiagoSD said in QProcess finish signal not emitted.:
while(proc.state()!=QProcess::NotRunning) std::cout<<" waiting:"<<proc.state()<<std::endl;
But this blocks, how will state get updated? Or finish get emitted?
BTW: are you (trying to) use threads because of wanting to run a process, not block, and be notified of finish? Because with
QProcess
and Qt it's asynchronous, you get that without needing threads. -
@JonB It is bocking a different thread.. not the Qt one.
I need to use threads for other purposes, the start of the application is not bound to the GUI , but to external events that are waited by a different thread (so when the external event happens I start the QProces.
I
-
As I guessed - there is no eventloop in the thread where QProcess lives.
No thread is needed at all for this task, and when then use QThread and run an eventloop. -
@Christian-Ehrlicher Ok, the problem is that the thread that I pass the lambda (that creaes the QProcess) is created by another library (not mine but i need to use it). So I will have to use somethign other than QProcess to handle this.
Thanks for the help anyway.
-
Then emit a signal there and move to a QThread with an eventloop or use QEventLoop directly.