qt - qprocess start in a loop - qt

I am calling a process in a loop. Need to ensure that one process ends before it starts again. how is it possible.
void MainWindow::setNewProjectInQueueList()
{
// this is already gotten in queueList now loop thru the list and add project
QStringList arguments;
projNm = ui->lineEditCreateProject->text();
qDebug() << " projNm " << projNm;
for (int j= 0; j < queueList.length(); j++)
{ if (! QString(queueList[j]).isEmpty())
{
// call process
// QString queueName = queueList[j];
arguments << "-sq" << queueList[j];
qDebug() << " arguments sq " << queueList[j];
procQueueList.start("qconf",arguments);
}
}
// and append for each queue with new project name
// and store into the system
}
Brgds,
kNish

Call QProcess::waitForFinished() to wait until the process terminates.

Using the waitForFinished approach from within a loop in the main thread will freeze the application. Instead, putting the loop in a separate thread, or making a queue of processes to start and then launch upon the finished signal from the previous one is good alternatives.

Related

Strange signal/slot behaviour

(Working with Qt 5.15.2)
I have a method which receives a signal (sig_responseReady) from the same thread. The purpose of this method is to wait until a response is received. While this method is waiting for the signal, the method is called again because of an event which calls this method (so eventloops get nested). However, the first waitForResponse on the stack does not get the sig_responseReady signal for up to 10 seconds (for no reason I can see), while later called waitForResponse get their signal first.
The result of this design is that I have nested eventloops, which according to this stackoverflow post causes slot/signal handling errors, and should be avoided. I suspect this is the cause of my problem.
Is there a design which accomplishes the same, with only a single eventloop? (I can't come up with it) The function which calls waitForResponse must pause until waitForResponse returns. ..I can't make it asynchronous. I tried replacing eventloop.exec with QCoreApplication::processEvents(QEventLoop::AllEvents,100) in the function below, but still get same strange result. (So maybe nested event loops is not the problem...but I can't figure out the cause)
MyClass::SRequest MyClass::waitForResponse(const QUuid queryID) {
reentryCount++; // Static var to determing nesting/depth count
QEventLoop eventloop;
qDebug() << "MyClass::waitForResponse connect for uid " << queryID << ", depth " << reentryCount;
connect(this,&MyClass::sig_responseReady,&eventloop, &QEventLoop::quit); //, Qt::QueuedConnection); // Allow matching response to stop eventloop
do {
eventloop.exec();
qDebug() << "MyClass::waitForResponse got signal for uid " << queryID;
} while (!queryResponseReady(queryID) && !queryExpired(queryID));
qDebug() << "MyClass::waitForResponse exitted loop for signal for uid " << queryID << ", depth " << reentryCount;
reentryCount--;
return queryTakeResult(queryID);
}

Unexplained time offset in QApplication event loop

I'm currently working with a program for predicting the locations of satellites in real-time. Something similar to this. The underlying library uses system time as input.
time_t now(time(0));
This program accurately predicts the real-time position of satellites when I run it on a C++ console application using Qt Creator.
The problem is when I use it in a fully-fledged Qt Gui application with a QApplication object in the main function. In the program, the prediction function is periodically by the timer event function. That way I update the positions every 2 seconds. Unfortunately, The output doesn't match (either on the GUI or when I print it). It is like the orbital propagator is using a different time when calculating the satellite positions.
void TrackingManager::timerEvent(QTimerEvent *event)
{
int nNumSats = m_Satellites.size() ;
//std::cout << __func__ << " - Number of satellites = " << nNumSats << std::endl;
std::vector<SatPosition> vSatPositions;
if (nNumSats >= 0)
{
time_t now(time(0));
std::cout << __func__ << "time(0) = " << asctime(gmtime(&now)) << std::endl;
for(int i = 0; i < nNumSats; i++)
{
// Get satellite names and calculate position, altitude etc
SatPosition spPos;
GetInstantPredict(m_Satellites[i], now, spPos);
vSatPositions.push_back(spPos);
}
emit UpdateSatPosition(vSatPositions);
}
}
Even more confusing, the program works fine when I run the debugger (GDB on Ubuntu). It is as if GDB somehow manages to "fix" the problem. Does this make any sense?

What is the reason asio doesn't do any delay?

I am new to asio.
Here is guide I was following writing my daytime tcp-server: https://think-async.com/Asio/asio-1.18.1/doc/asio/tutorial/tutdaytime3.html . I was trying to reproduce a reasonable example that would show that asunchronous code is actually asynchronous. I didn't modify anything else, just small piece of code in tcp_server class. I am adding this delay in order to see that after we are waiting timer to expire, we can gracefully handle other client connections/requests. So, did I miss something? Because in my case delay basically doesn't work ;(
void handle_accept(const tcp_connection::pointer &new_connection,
const asio::error_code &error) {
asio::steady_timer timer(io_context_, asio::chrono::seconds(5));
std::cout << "Before timer" << std::endl;
timer.async_wait(std::bind(&tcp_server::handle_wait, this, error, new_connection));
}
void handle_wait(asio::error_code &ec, const tcp_connection::pointer &new_connection) {
if (!ec) {
new_connection->start();
}
std::cout << "Inside timer" << std::endl;
start_accept();
}
void handle_accept(const tcp_connection::pointer &new_connection,
const asio::error_code &error) {
asio::steady_timer timer(io_context_, asio::chrono::seconds(5));
std::cout << "Before timer" << std::endl;
timer.async_wait(std::bind(&tcp_server::handle_wait, this, error, new_connection));
}
The timer is a local variable.
async_wait returns immediately, without blocking.
The function exits, destructing the timer. The timer cancels all pending operations (with error::operation_aborted).
🖛 Make sure the lifetime of the timer extends well enough to allow for it expire (or at least until it stops being relevant). In your case there will probably already be a tcp::acceptor member in your class, and the timer could reside next to it.

Error on adding to empty comboBox in Qt

I use Qt 5.2.0 (MSVC 2010).
I added to my form in Qt a ComboBox.
Then I want to fill it with numbers:
for (i = 0; i < n; i++){
ui->tableCombo->addItem(QString::number(i));
}
When I add a first element right in the form, it successfully adds numbers. But when I leave it empty, it throws an error:
ASSERT failure in QVector::operator[]: "index out of range"
Debugger shows that error occured right in this line. And there is no QVector across the line.
After adding qDebug().
qDebug() << "readFileToStringList: msg10";
for (i = 0; i < n; i++){
qDebug() << "readFileToStringList: msg20 i = " << i;
ui->tableCombo->addItem(QString::number(i+1));
qDebug() << "readFileToStringList: msg30";
}
qDebug() << "readFileToStringList: msg40";
I get the same result
readFileToStringList: msg10
readFileToStringList: msg20 i = 0
ASSERT failure in QVector<T>::operator[]: "index out of range", file C:\Qt\Qt5.2.0\5.2.0\mingw48_32\include/QtCore/qvector.h, line 369
I had this exact problem and couldn't figure it out for a couple hours. I realized ::addItem() was triggering the indexChanged(int) signal, which I had connected to a function that was causing an out-of-range error in a container.
I would say it was possibly the problem here too, but I'm sure the OP has moved on since then. To me it isn't exactly intuitive that the indexChanged signal would be called on insertion of new items, since it doesn't actually change the currentIndex.
Hopefully if anyone else gets tripped up this will help them!
addItem() doesn't throw that error! I'm positive it's coming from another instruction in your code.
Qt documentation has an entire section on Debugging Techniques, but if you are afraid of debuggers you can use the poor's man debugger: spread several qDebug() messages before and after the instructions you think are responsible for the problem:
qDebug() << "methodX: msg10";
for (i = 0; i < n; i++){
qDebug() << "methodX: msg20 i = " << i;
ui->tableCombo->addItem(QString::number(i));
qDebug() << "methodX: msg30";
}
qDebug() << "methodX: msg40";
If the message methodX: msg30 gets printed to the screen, means that addItem() didn't cause the error.

If I reuse a QProcess variable, can there be leftover data in the stdout/stderr channels?

I have the following scenario:
QProcess*p;
// later
p->start();
//later
p->terminate(); // there might be unread data in stdout
//later
p->start();
I read the process stdout. After I call p->start() the second time, could there still be unread data left in the stdout buffers from the first p->start()? That would be a problem for me. Do I need to flush the buffers or something?
Okay, I've checked the sources. The QProcess::start() method explicitly clears both output buffers, so it should be okay, at least in this sense:
void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
{
Q_D(QProcess);
if (d->processState != NotRunning) {
qWarning("QProcess::start: Process is already running");
return;
}
#if defined QPROCESS_DEBUG
qDebug() << "QProcess::start(" << program << "," << arguments << "," << mode << ")";
#endif
d->outputReadBuffer.clear();
d->errorReadBuffer.clear();
I still think it's a bad style to reuse the same object, though.

Resources