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.
Related
As the title says, do you know if a killed process in Qt calls the finished signal?
From the docs finished and kill is not clear to me.
Even if I could do a test, I would like to know an official answer, so that I am sure the behaviour is the same in every machine, in every operating system etc. etc.
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.
In my Qt C++ program I created a process as follows:
myProcess = new QProcess();
myProcess->start(programpath, arguments);
Terminating the process is handled as follows:
myProcess->terminate();
Terminating the child process with QProcess::kill(),terminate() or close() works, but I don't want to use it because it doesn't give the child process a chance to clean up before exiting.
Is there any other way to exit the process? Thanks!
The polite way would be for the parent process to politely ask the child process to go away. Then when the child process exits (of its own volition), the QProcess object will emit a finished(int, QProcess::ExitStatus) signal, and you can have a slot connected to that signal that will continue your process (e.g. by deleting the QProcess object at that time). (Or if you don't mind blocking your Qt event loop for a little while, you could just call waitForFinished() on the QProcess object after asking it to exit, and waitForFinished() won't return until the process has gone away or the timeout period has elapsed)
Of course for the above to work you need some way to ask the child process to exit. How you go about doing that will depend on what the child process is running. If you're lucky, you are in control of the child process's code, in which case you can modify it to exit in response to some action of the parent process -- for example, you could code the child process to exit when its stdin descriptor is closed, and have the parent process call closeWriteChannel() on the QProcess object to cause that to happen. Or if you're running under Linux/Unix you could send a SIGINT signal to the child process and the child process could set up a handler that would catch the signal and start an orderly shutdown. Or if you want something really stupid-quick and dirty, have the child process periodically check for the presence of a file at a well-known location (e.g. "/tmp/hey-child-process-PIDNUMBERHERE-go-away.txt" or something) and the parent process would create such a file when it wants the child to go away. Not that I'd recommend that last method as I don't think it would be very robust, except maybe as a proof of concept.
terminate actually gives the process an chance to clean up. The program being terminated just has to take that chance i.e. the system sents a SIGTERM and the application and it can ignore that and exit cleanly on its own. If this is still not nice enough then you have to implement your own way of asking the application to quit. Jeremy Friesner made some good successions. If the application code is not written by yourself you'll have to read the documentation for that program closer, maybe its documented how to do that.
My windows/QT application is not exiting consistently.
After the object clean up, I am trying to delete the QProcess object. But it's not cleaning up the process and it can be shown in the task manager.
delete process;
process = 0;
I think delete process is not working because some threads are running at the background. I want to ensure that all threads are closed gracefully, so the process will exit.
Please let me know the right way to do this.
The task manager does not show your QProcess object, and deleting that object will not affect the task manager. If there is still code running in your process, the process will continue to exist according to the OS.
If you really want to exit the process, you can call the Win32 function ExitProcess(). Just make sure you've saved everything you want to.
Qt will normally exit the process when all your threads stop running.
One problem may be that the QProcess object doesn't represent a child thread, it represents an independent process, you probably want to use the QThread object.
With the QThread object you can use some combination of the quit, exit, wait, and terminate depending on the exact content of you child thread, check the documentation for the differences.
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.