I am developing a windows form application with Qt 5.0.2. I need to call another program during mine, which is a console application. I want to pass the arguments through command line or a file, and read the expecting results via another file, but, because of some reasons I need to when the program finishes its work and the expecting file is ready to be read.
My process is defined as follow :
QProcess *p;
p = new QProcess(this);
QStringList args;
args << "babak" << "Ali" << "Mohsen";
p->execute("ConsoleApplicationCSH.exe" ,args)
I know I could use start instead of execute, but the result was the same. I tried to check it out through this code:
while(!p->waitForFinished()){
;
}
exit(1);
The called is written is way that it takes around 10 sec to finishes it process, but the while loop does not finishes. I checked the other form of using this method and some similar methods but I didn`t get any good result.
First, you need to use QProcess::start() instead of QProcess::execute(): execute() is a static method running the process and blocking until it's done. So the process is already finished when execute() returns. Use start() to run the process without blocking.
Then, in GUI code, you should connect to the finished() and error() signals to learn about both successful termination and errors (check errorString() in case of errors).
If run in the main thread, waitForFinished() blocks the UI, thus it's usually undesirable to use the blocking calls. Note that waitForFinished() returns false not only on timeout, but "if the operation timed out, if an error occurred, or if this QProcess is already finished". Connecting to finished() and error() is a more robust way to detect error cases. If you really want to it in a blocking way (e.g. in a secondary thread or in a non-GUI program), call QProcess::waitForStarted() first, to detect cases where the process couldn't even be started more cleanly.
Related
Introduction
Lets say I have an app with GUI, which gathers some data from the user and then call an embedded python script. I want to add "cancel button" in case the user want to stop the process.
Exemplary code
mainwindow
#include "calc_script.h"
signals:
void stopWorkSignal();
private:
calc_script *sender;
private slots:
Calculating()
on_pushButton_Cancel_clicked()
void MainWindow::Calculating()
{
QThread* newThread = new QThread();
connect(newThread, &QThread::started,
[=]() { sender->transfer(val_1, val_2, val_3); });
connect(this,
SIGNAL(stopWorkSignal()),
newThread,
SLOT(deleteLater())
newThread->start();
}
void MainWindow::on_pushButton_Cancel_clicked()
{
emit stopWorkSignal();
qDebug() << "stopwork signal emmitted";
}
calc_script.cpp
void calc_script::transfer(double val_1, double val_2, double val_3)
{
///Here the python (from boost.python) is executed
while(1) {}//this loop will generate a load to mimic this script, you cannot edit it, as the communication with .py is one-side at this lvl
}
The problem
When the signal is called I got the error QThread destroyed while thread is still running (and calculation seems to be still going). If I pass SLOT(quit()), nothing happens. If the calculation would be simple loop, I could pass a flag, to brake the loop. But due to calling python script I'm unable to do this, so I'm trying with destroying the Thread which hold the calculations. What's the correct way to do described functionality?
PS. I know I didn't included entire call to python but it is very long. For the reproduction error you can use any non-loop long calculations inside transfer function, it will do basically the same situation.
You can't forcibly terminate a thread; all you can do is ask it to quit, and then wait for it to exit of its own accord. (there does exist a QThread::terminate() method, but you shouldn't use it in production code, as it will cause problems: for example, if the thread had a mutex locked at the moment it got terminated, that mutex will remain locked forever, and your program will deadlock and freeze up the next time it attempts to lock that mutex).
So you have two options: either figure out a way to ask the Python thread to quit, or use a QProcess object (or something equivalent to it) to run the Python code in a child process instead of inside a thread. The benefit of running the Python code in a separate process is that you can safely kill() a child process -- since the child process doesn't share any state with your GUI process, and the OS will automatically clean up any resources allocated by the child process, there is no problem with the child process leaving mutexes locked or other resources un-freed.
If you'd rather ask the Python thread (or process) politely to exit instead of simply bringing down the hammer on it, you could do so via a networking interface; for example, you could create a TCP connection between your GUI code and the Python event loop, and the Python event loop could periodically do a non-blocking read on its end of the TCP connection. Then when your GUI wants the Python loop to exit, the GUI could close its TCP socket, and that would cause the Python loop's call to read() to return 0 (aka EOF), which the Python loop would know means "time to exit", so it could then exit voluntarily.
I'm making a render job manager for blender. I have a class that builds up a queue of render jobs and then you click Start and it begins rendering one at a time with a loop. My problem is that the waitForFinished() method holds up my entire program. But I've read that you shouldn't use QThread with QProcess.
This is how the loop works.
do{
if(myProcess->state() == QProcess::NotRunning) {
myProcess->setProgram(blenderPath);
myProcess->setArguments(arguments);
myProcess->start();
myProcess->waitForFinished(-1);
//Get rid of current rendering job to prepare for the next job
renderQueueList.pop_front();
}
}while(renderQueueList.empty() != true);
Can I use a separate thread to launch QProcess and what would be the best way to do this? I've read that you make an abstract of QThread or use signals and slots but it's so confusing, specially when I need to pass arguments to the process.
Thank you.
Edit:
I want to add that the process must finish before running a new process. It has to go in order. That's why I think I need the process to run in its own thread.
QProcess already executes in a different process, i.e. asynchronously with your application.
When you call waitForFinished() the application locks up until the process in QProcess finishes. You need to connect instead to the finished() and probably errorOccured() signals, and then your application will keep running while the QProcess runs in the background.
You'll need to change that loop to a check that the queue isn't empty and a new process start on the finished() signal.
If you run a QThread that runs QProcesses and does waitForFinished() you will free the main application thread indeed, but it's a pointless extra layer when QProcess is asynchronous already and you have have finished() to let you know when it's done without locking up a thread, be it the UI thread or a separate one.
My problem is that I am starting an executable in a QProcess like the following:
QProcess Work;
Work.start(program.exe);
This executable runs since it has been started in background and I can send requests to it. If I have finished I am closing the executable the following way:
Work.close();
But if I am looking at the Taskmanager the program.exe is running furthermore. I dont understand that behaviour because I thought the executable would been stopped if I close the Process.
You should use void QProcess::terminate() or void QProcess::kill() for it.
terminate() - attempts to terminate the process.
kill() - kills process immediately.
I had a very similar case, although I was working on linux embedded with QT 4.8. Not sure if this can help you, but since I can't put it in a comment, I have to make a separate answer.
Do you set a parent to your QProcess? In my case, I instantiated QProcess like this
QProcess *p = new QProcess;
and I could see in the running processes list that each time I instantiated a new QProcess, I got a new process that couldn't be closed by close(), terminate() or kill(). When I finally rewrote the code like this
QProcess *p = new QProcess(mainW); //mainW was my GUI class, which handled also the closing of the process
the problem solved itself, I didn't even need to call any function to close the process. In my case I was sure the processes I called were finishing, since almost all of them were audio files, so I could hear them finishing. The others were processes that my program waited to complete, so again I was sure they ended because my program wasn't stuck waiting for them,
Hope this can help, despite the different OS.
I'm using a List of QProcess objects to keep track of some processes that need to be start/stopped at user defined intervals.
I'm able to start and stop the processes OK. But the issue arises when I stop a process using the following methods (Pseudo code):
process->start("PathToProcess","Some Arguments");
//Do some stuff.
process->terminate();
However, if I try to start the process again at another time, I get the error:
QProcess::start: Process is already running
I can do a ps -ef|grep processName and find that it is indeed dead, but it's sitting in a defunct state which I think is preventing me from starting it again.
What do I need to do to prevent this defunct state, or remove the defunct method so I can start my process again without reconstruction?
Figured out what was causing the error.
In qprocess_unix.cpp, you'll find a class called QProcessManager. Essentially this class has signal handlers that watch for child processes that have died. When a child dies, the QProcessManager sends a message across a pipe that lets the QProcess class know that it terminated/died.
In a unrelated part of my code, I had set up some signal catching statements that I used for various puposes. However, these signal catches were catching my SIGCHLD event and thus the QProcessManager was never being triggered to pipe to the QProcess that it died.
In my case, my only options are to either watch for the death of the child manually or to remove the signal catching I'm performing in my other sections of code.
For future reference, if you have this problem, you may be better off doing POSIX calls for kills and terminates, and checking the return value of those calls manually. If success, perform a:
process->setProcessState(ProcessState::NotRunning);//Specify the process is no longer running
waitpid(process->pid(),NULL,WNOHANG); //Clear the defunct process.
Thanks all.
Call process->waitForFinished() after calling process->terminate() in order to reap the zombie process. Then you can reuse the process object.
I need to execute some commands via "/bin/sh" from a daemon. Some times these commands takes too long to execute, and I need to somehow interrupt them. The daemon is written in C++, and the commands are executed with std::system(). I need the stack cleaned up so that destructors are called when the thread dies. (Catching the event in a C++ exception-handler would be perfect).
The threads are created using boost:thread. Unfortunately, neither boost::thread::interrupt() or pthread_cancel() are useful in this case.
I can imagine several ways to do this, from writing my own version of system(), to finding the child's process-id and signal() it. But there must be a simpler way?
Any command executed using the system command is executed in a new process. Unfortunately system halts the execution of the current process until the new process completes. If the sub process hangs the new process hangs as well.
The way to get round this is to use fork to create a new process and call one of the exec calls to execute the desired command. Your main process can then wait on the child process's Process Id (pid). The timeout can be achieve by generating a SIGALRM using the alarm call before the wait call.
If the sub process times out you can kill it using the kill command. Try first with SIGTERM, if that fails you can try again will SIGKILL, this will certainly kill the child process.
Some more information on fork and exec can be found here
I did not try boost::process, as it is not part of boost. I did however try ACE_Process, which showed some strange behavior (the time-outs sometimes worked and sometimes did not work). So I wrote a simple std::system replacement, that polls for the status of the running process (effectively removing the problems with process-wide signals and alarms on a multi threading process). I also use boost::this_thread::sleep(), so that boost::thread::interrupt() should work as an alternative or in addition to the time-out.
Stackoverflow.com does not work very good with my Firefox under Debian (in fact, I could not reply at all, I had to start Windows in a VM) or Opera (in my VM), so I'm unable to post the code in a readable manner. My prototype (before I moved it to the actual application) is available here: http://www.jgaa.com/files/ExternProcess.cpp
You can try to look at Boost.Process:
Where is Boost.Process?
I have been waiting for a long time for such a class.
If you are willing to use Qt, a nice portable solution is QProcess:
http://doc.trolltech.com/4.1/qprocess.html
Of course, you can also make your own system-specific solution like Let_Me_Be suggests.
Anyway you'd probably have to get rid of the system() function call and replace it by a more powerful alternative.