Solved QProcess freezes UI
-
Hello,
I'm using a QProcess to run system commands but it freezes the UI while using waitForFinished which is normal as its indicated in the documentation. I tried to use signals and slots but it still freezes. Here is my code:
bool NetworkConnection::connectEthernetDynamic(){ QProcess con_process = new QProcess; con_process->start("nmcli con add type ethernet con-name my_connection ifname eth0"); connect(con_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this, con_process](int exitCode, QProcess::ExitStatus exitStatus){ QString output2(con_process->readAllStandardOutput()); if (output2.contains("successfully")){ QProcess process; process.start("nmcli con up my_connection"); process.waitForFinished(); QString output3(process.readAllStandardOutput()); return output3.contains("successfully"); } }); }
-
Hi,
Signals and slots does not mean that the slot is executed in a different thread. The only time it is the case is when the target thread affinity is a different thread than the one where the signal is originating.
-
@Iheb
What can we say other than: your outerQProcess
does not usewaitForFinished()
, so it does not block. But if you getsuccessfully
back, you then create anotherQProcess
which does callwaitForFinished()
. Hence that blocks.I tried to use signals and slots but it still freezes.
Show what you did, because signals & slots will not block/freeze. One way would be: if you make your inner process do a signal on
QProcess::finished
just like you outer one does, that would be a starting approach. -
@SGaist Hi, so what should I do?
-
@Iheb said in QProcess freezes UI:
@SGaist Hi, so what should I do?
@JonB said in QProcess freezes UI:
One way would be: if you make your inner process do a signal on QProcess::finished just like you outer one does, that would be a starting approach.
Did you choose to ignore this suggestion? Or do you only wish @SGaist to respond?
-
@JonB Yes I thought about that too and I tried something like this but it still freezes
bool NetworkConnection::connectEthernetDynamic(){ auto con_process = new QProcess; con_process->start("nmcli con add type ethernet con-name my_connection ifname eth0"); connect(con_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this, con_process](int exitCode, QProcess::ExitStatus exitStatus){ QString output2(con_process->readAllStandardOutput()); if (output2.contains("successfully")){ auto process = new QProcess; process->start("nmcli con up my_connection"); connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this, process](int exitCode, QProcess::ExitStatus exitStatus){ QString output3(process->readAllStandardOutput()); return output3.contains("successfully"); }); } }); }
-
@Iheb
Looking through, I would not expect this to "freeze", whatever else it might do. Put it someqDebug()
statements, immediately before & after thestart()
lines and at each step in the slots. You/we need to understand what line you say it blocks/freezes on in the code you show.EDIT Oohh, I just noticed: you are connecting your slots after you have issued the
start()
statement. You must not do that, it may (well) be missed!connect()
the signal/slot immediately after creating theQProcess
instances, before you gostart()
on them.As a separate observation, once you have this working satisfactorily you will need to delete the two
QProcess
es you create which currently leak. -
-
@Iheb said in QProcess freezes UI:
@JonB I didn't choose to ignore your suggestion nor wishing only @SGaist to reply I simply just have about 10 min 1-reply interval (I don't have enough reputation to reply so I have to wait 10 min between each one)
Not a problem :) Read my latest response above, including the need to change the order of your statements, and let us know.
-
@Iheb
And a further observation, which might affect how you are (trying to) use this code.The
return output3.contains("successfully")
statement only returns a result for the slot connected to the secondQProcess
--- which is thrown away, as nobody cares about it.Meanwhile you have
bool NetworkConnection::connectEthernetDynamic()
, which at present is not returning any result itself. I am surprised you do not get a compiler warning for this? You must arrange your code differently, yourconnectEthernetDynamic()
is non-blocking (as you desire) so it cannot return a value about the completion of the processes. Instead it will return immediately. So if you need to use the second process's output result, you will need to change how you do that. But you should be able to get the processes running without freeze initially if you skip needing the result. -
@Iheb said in QProcess freezes UI:
@SGaist Hi, so what should I do?
As @JonB suggests, rethink your design to properly take advantage of the asynchronous nature of Qt.
-
@JonB Hi again, I confirm your suggestion works well. I found that I have another QProcess running just before the function and has waitforfinished. Using nested signal and slots for QProcess won't freeze the UI. I also managed to arrange my code to work as desired and the
connectEthernetDynamic()
became avoid
function. -
@Iheb Could you share your new working code please?