What is wrong with this code? I can not write to stdin of new process that has been detached.
It is important for me that the new process is detached.
QProcess commandLine;
commandLine.setWorkingDirectory("E:\\"); //does not work.
commandLine.startDetached("cmd.exe"); //works (but uses wrong working dir).
commandLine.write("echo hi\0"); //writes nothing.
commandLine.write("\n\r"); //Still nothing is written!
Good morning.
The problem is that QProcess::startDetached() is a static method which creates a "fire and forget" process.
This means, that you cannot set a working directory this way. All you can do is call
QProcess::startDetached (const QString &program, const QStringList &arguments, const QString &workingDirectory);
This however leaves you with the problem of writing to the stdin of the newly created process. The thing is, since you don't have a QProcess object there is nothing you can write your stdin to. There could be a solution using the process handle the static startDetached() method's providing.
We had the similar problem in our company. We needed detached processes which ran beyond the lifespan of the calling programm and for which we could set the environment. This seemed, looking at the Qt code, impossible.
My solution was to use a wrapper around QProcess with its own startDetached() method.
What it did, it actually created this QProcess subclass on the heap and used its ordinary start() method. In this mode however the signal, which fires once the process has finished, calles upon a slot which deletes the object itself: delete this;. It works. The process is running independently and we can set an environment.
So basically there is no need to use the detached start method. You can use the ordinary start method as long as your QProcess is an object on the heap. And if you care for memory leaks in this scenario you'd have to provide a similar mechanism as described above.
Best regards
D
call static method with arguments doesn't provide any set of process into child command.
process.startDetached(command)
try this:
QProcess process;
process.setProgram(fileName);
process.setArgument(argsList);
process.setWorkingDirectory(dirName);
process.startDetached();
Related
using QtCreator to make a loftier interface to a sofware.
There is basically a set of buttons to tune and inputs, a start and stop job
buttons, my problem comes from an infinite loop that freezes the display so I came up with using fork() so that the loop have to compete with the main program instead of eating up the whole resources (no multithreading), but the program crashes spiting:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not
been called
[xcb] Aborting, sorry about that.
a.out: ../../src/xcb_io.c:274: poll_for_event: Assertion
`!xcb_xlib_threads_sequence_lost' failed.
the fonction calling the loop is called 'ON', 'OFF' is supposed to exit the forked process.
//in button 'ON' func
ps = fork();
if(getpid() == ps)
{
while(1)
{
strcpy(word, charset(minlength, maxlength, N));
ui->pass->setText(word);//operation on the display
....SNIP
}
}
//In button 'OFF' func
if(getpid() == ps)
exit(0);
I'm really asking what is the correct way of starting a while(1) and be able to break, exit, or return from it while not freezing the window using QT, thanks.
You crash probably here:
ui->pass->setText(word);//operation on the display
as in Qt, you can not change UI from non UI threads directly. Only from signals and slots mechanism.
The proper way to not freeze UI is obviously to compute lengthy operations in another thread.
You can achieve this in several ways:
One is by sub-classing QObject class to create 'worker object' which would perform all heavy operations. You create new QThread object that should live as long as you need your object. And use QObject::moveToThread method to move created object to new thread. To control your worker object you should send signals from object and call it's slots also via signal-slot mechanism. If you call them directly - they will be executed in caller thread (so do not perform stuff like worker->startHeavyJob(); in UI thread). Instead emit signal in UI (emit sigStartHeavyStuff();) and connect it to slot of your worker object (slotDoHeavyStuff();)
if you do not want to bother with this (if operation is pretty small)
- you can use QApplication::processEvents() to process events in UI event loop while going in your infinite while loop.
Another way is to use QtConcurrentRun framework to run function in separate thread which manages itself. Threads are taken from thread pool and are managed by Qt. This approach looks like something you want to do. Though you still will be able to access UI objects only through signals and slots.
I see one big issue in the presented code that is causing your freeze: You never let Qt process anything while you are in the loop. You need to allow Qt to run it's event loop. The easiest way is to use QApplication::processEvents() inside the loop.
I'm also not a fan of a while(1) loop for a couple of reasons. The first of which is that it can eat machine cycles waiting for things to happen. I doubt you really need to run the code as fast as possible, you could probably get away with some sleeping in your loop.
The other issue is that it is hard to break out. A cleaner approach would be something like this
void MyClass::on_pushButton_ON_clicked()
{
MyClass::done = false; // this is a class attribute
while (!MyClass::done) {
QApplication::processEvents();
//...
}
}
void MyClass::on_pushButton_OFF_clicked()
{
MyClass::done = true;
}
I am working on an Spark project which has an executable which starts the process in background , now I need to know when the process gets killed through Bash.The only solution I got is to continuously check its PID existence through grep in loop if exist or not , Is there any other possible solution that do it without looping around .
I also tried handling the exit codes ,but the exit code is 0 if process runs and only changes when it gets killed which need to be checked continuously
If I understand right, the situation is this:
Your executable does somewhere fork and run another logic in another process, and you want the main process to get notify whether the forked process is still running.
In order to answer I'll make sure we both are familiar with the same terminology:
The main process (when you run your executable) is called the parent process.
The process that the parent process is starting, is called the child process.
Now when a child process dies a signal SIGCHLD is sent to the parent process, Normally SIGCHLD is mapped to SIG_DFL which is actually SIG_IGN for SIGCHLD. In human words, it means that the parent process does not give a shit if the child process dies.
But, If you want to get notify, you may change the behaviour of what happens when SIGCHLD is sent. In order to do so you must implement signal handler function:
void custom_sigchld_handler(int sig)
{
pid_t p;
int status;
while ((p = waitpid(-1, &status, WNOHANG)) != -1)
{
// If you got here it means p is a dead process. Do your logic here...
}
}
Then you must declare that you want our custom_sigchld_handler to take care of SIGCHLD signals:
struct sigaction signal_action = {0};
signal_action.sa_handler = custom_sigchld_handler;
sigaction(SIGCHLD, &signal_action, NULL);
May need a little more context... if your executable is starting the process, there is surely a way to get or keep a handle on it while executing.
In php, there is proc_open(), in Qt there is the QProcess class, in c/c++, there is popen()
Many languages have this feature, but without more details it's hard to offer a solution.
I want to pause my program for some seconds in a program that i'm writing by c++ Qt.in fact when the program arrive to one of my functions it stops for for example 5 seconds and then continue next lines.what should I do?
that function is a member function of a class and I want to o that work(pausing)for each instance of the class...
In case you really need to do that, you have several options
You can use QThread's sleep methods by inheriting QThread and making them public (those are protected because it's generally a bad idea)
Or you can use QEventLoop exec together with QTimer. Connect timer's signal to QEventLoop's quit() slot. That will cause "non-blocking" wait, so your app will not stay frozen.
Or maybe you should instead split your code into two methods, make the second one a slot and call it with a timer when appropriate
EDIT: something like, in your eat method you use QTimer::singleShot to call finishEating slot after X seconds.
You might also want to read this: http://qt-project.org/doc/qt-5.0/qtcore/thread-basics.html
If you are using Qt5 you can use the following trick:
QMutex mut;
mut.lock();
mut.tryLock(milliseconds);
mut.unlock(); // I am not sure if this is a necessity
With Qt4 you can use QWaitCondition::wait() on the mutex;
Keep in mind that if this is in your interface thread your gui will freeze until the interval ellapses.
I have a multi document program (call it HostProgram) . I would wish to have a process (call it GuestProcess) managing each open documents inside HostProgram in order to improve stability (if one of the Guest Process crashes I'm not forced to close the HostProgram and the other running GuestProccesses).
Is it possible using Qt library to render the GUI composing GuestProcess inside a SubWindow of HostProcess? If yes how?
Thanks in advance a lot for any help/hints you will be able to provide me.
If i right undestand your problem, then you can help:
bool QProcess::startDetached ( const QString & program, const QStringList & arguments) [static]
Starts the program program with the given arguments in a new process, and detaches from it. Returns true on success; otherwise returns false. If the calling process exits, the detached process will continue to live.
For example:
QProcess process;
process.setProcessChannelMode(QProcess::ForwardedChannels);
process.startDetached(/*you new task*/);
Well i've been looking how to do an auto updater on google, however no success.
What i would plan is to create an updater (ANother exe called by QProcess though the principal exe) but here ihave some questions:
How do i make the QProcess silent?
If there's a new version, how do i show a notification on the window from where the process has been started (I meant i've create the process in Game.exe, i want to send a notification to Game.exe from Updater.exe that there's a new version available.)
Thanks for the answers.
First, I've never encountered a need to create anything other than a QThread to handle my update needs. The QProcess would be helpful if, once the user updates, you want to download, install, and relaunch the program while the user continues with the main program. (But this can all be achieved with a shell script, python script, even BAT file)
When you use QProcess, you will have to rely on the signals readyReadStandardError() and readyReadStandardOutput(). Then the application that your process is calling should send its output to stderr or stdout. Updater.exe should write to either of these files.
I would imagine your Updater to make use of QNetworkAccessManager::finished(QNetworkReply *reply). When this slot is called, please do something nicer than this:
void Updater::replyFinished(QNetworkReply *reply){
QString r(reply->readAll());
if(r.contains(SERVER_REPLY_UPDATE_AVAILABLE)){
qDebug() << "yes";
}else{
qDebug() << "no";
QApplication::quit();
}
}
If Updater.exe is going to be a full blown GUI application, do not call the show() method unless it's needed and it should appear to run in the background. I would prefer a script, but you know me.
Then your Game.exe will set up a QProcess. You can pass arguments to the process within the QProcess::start() function.
Good arguments that will help direct your update process would be:
Game.exe version number
"check_for_updates"
"ignore_updates"
"download_update"
finally, in Game.exe:
...
connect(process,SIGNAL(readyReadStandardError()),this,SLOT(readProcessReply()));
...
void Game::readProcessReply(){
QString r(process->readAllStandardError());
if(r.contains("yes")){
//show your dialog here
}else{
//do nothing
}
}