QSharedMemory : Second process cannot attach - qt

I have 2 processes.
The first one creates a QSharedMemory, with a key.
The creation is successful, as no error is returned.
In the second process, I try and attach to the shared memory, having done setKey() with the same key name as the first process, and then try and attach() to the memory.
The attach() fails. Using errorString() on the shared memory, the following string is returned :
QSharedMemory::handle: doesn't exist
Platform is Windows.
What could I be missing here? Kindly advise, thanks.

Have you looked at the shared memory example?
http://doc-snapshot.qt-project.org/4.8/ipc-sharedmemory.html
Below are some code snippets from that example.
Here is what the first process does to put a buffer of "size" into the shared memory:
if (!sharedMemory.create(size)) {
ui.label->setText(tr("Unable to create shared memory segment."));
return;
}
sharedMemory.lock();
char *to = (char*)sharedMemory.data();
const char *from = buffer.data().data();
memcpy(to, from, qMin(sharedMemory.size(), size));
sharedMemory.unlock();
Here is what happens when the second process wants to access the shared memory:
if (!sharedMemory.attach()) {
ui.label->setText(tr("Unable to attach to shared memory segment.\n" \
"Load an image first."));
return;
}
QBuffer buffer;
QDataStream in(&buffer);
QImage image;
sharedMemory.lock();
buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());
buffer.open(QBuffer::ReadOnly);
in >> image;
sharedMemory.unlock();
sharedMemory.detach();
ui.label->setPixmap(QPixmap::fromImage(image));
Note also that in the example, both processes must be running and still have their instance of QSharedMemory. Here is how it is described in the documentation:
Windows: QSharedMemory does not "own" the shared memory segment. When
all threads or processes that have an instance of QSharedMemory
attached to a particular shared memory segment have either destroyed
their instance of QSharedMemory or exited, the Windows kernel releases
the shared memory segment automatically.
Hope that helps.

Encountered same problem. Make sure that QSharedMemory object still lives when second binary tries to attach.
If you want to block ability to run 2 instances of same QT binary, just make QSharedMemory object using dynamic memory which will live until app exit.

Related

Why the task of QThread can not be executed until the function returns

For example:
void MainWidget::testThreadTask()
{
qDebug() << "On test task";
}
void MainWidget::onBtnClick()
{
QThread *thread = new QThread;
connect(thread, QThread::started, this, testThreadTask);
thread->start();
qDebug() << "Thread START, now we wait 5s";
QElapsedTimer timer;
timer.start();
while (timer.elapsed() < 5000)
{
}
qDebug() << "END";
}
The program output is:
START wait 5s
END
On test task
I want to create a task to handle something after the button is pressed, and then the function will wait for the task to complete before returning.
In fact, it may not be necessary to create a new task and wait for it to execute, because since you have to wait and get stuck there, why not run it directly in the function.
But this is actually a problem when I deal with QT serial data. I want to send the data to the serial port after pressing the button, and then wait for the data (by constantly reading), but I find that when I have been waiting, the serial port can not read the data at all, only when I exit the function the serial port can read the data.
Is there any way to deal with serial data sending and receiving synchronization?
void MainWidget::onBtnClick()
{
serial->write("Test");
if (serial->bytesAvailable())
{
QByteArray data = serialIo->readAll();
// handle the data
}
}
You are mistaken with what is happening in your application. I suggest you read Threads and QObjects (the entire page), Qt::ConnectionType and the detailed description of QThread.
What is happening to you is:
MainWidget does not live in thread. For the slot of a regular object to be called from thread, it first needs to be moved to that thread.Note that subclasses of QWidget cannot be moved to another thread. Because some OS supported by Qt limit where windows can live, they made the choice to force all QWidget to stay in the main thread, in all OS Qt can execute on.
When you connect thread to this (which BTW is incorrect in your question, it should have been with ampersands connect(thread, &QThread::started, this, &MainWidget::testThreadTask);), you create a queued connection, even though the thread has not technically started yet.
When you start the thread:
It fires its started signal.
Because the connection is a Qt::QueuedConnection, the slot will only be executed after returning to the main thread's event loop, i.e. some time after returning from onBtnClick.
Notes:
You would have more useful information in qDebug() about the threads running your code by using QThread::currentThread().Even better than that, your IDE should provide you a window specifically to see what thread has reached a breakpoint (Ctrl+Alt+H on Visual Studio).
At the risk of insisting, keep in mind this warning from the Qt help:
Be aware that using direct connections when the sender and receiver live in different threads is unsafe if an event loop is running in the receiver's thread, for the same reason that calling any function on an object living in another thread is unsafe.
With that said, because you wait 5 seconds before returning to the event loop and because it is only test code (= there should be no bug + it does not matter even if there is one), you should try to create a Qt::DirectConnection, just to see the slot be invoked from the worker thread.
The detailed description of QThread (link above) shows a complete working example of a worker object being moved to the new thread before it is started. The point is:
A worker object is created, then moved to the worker thread.
Connections are created for the controller to send QString to the worker object via signal/slot and for the worker object to return result to the controller via signal/slot too.
All these connections are Qt::QueuedConnection by default since the worker object was moved.
The worker thread is started. Since run was not overriden, it starts an event loop (in exec).
And there you have it.
Remember 1 things: widgets cannot be moved!!! Create your own worker object.

QThread Barrier mechanizm in Cpp

How can I define a barrier point In a Qthread run() method for synchronization.
My run method code consists of two stages, and all of the threads must reach the end of the first stage before they can pass the second stage.
void ThreadClass::run()
{
barrier// All of the thread must reach this point before passing below the line
}
From the top of my head ::
1 : Create a mutex and then lock it in your main() before creating the thread pool. Create the thread pool, let them run, your barrier should read like this.
perThreadReachedThisPointFlag = 1;
mutexCreatedByMain.lock();
mutexCreatedByMain.unlock();
In your main(), monitor the thread pool. If you observe (do not forget the memory fences) that all the threads in the pool have set the perThreadReachedThisPointFlag, then execute mutexCreatedByMain.unlock(); on your main().
All the threads were waiting to lock the mentioned mutex, then you let them go. All of them will lock then unlock the mutex.
2 : Another way would be using conditionVariable and conditionSignal functionality of pthread but I do not know a replacement for Windows.

Deleting a pointer to array and UMDH log

I was investigating a memory leak with the application written in C# & C++. Once I have isolated it to couple of C++ components with PerfMon log and WinDbg/SOS debugging I tried to use UMDH (gflags enabled with +ust) to compare snapshots and find out which heap allocations were leaking memory.
At end the leak was found by a manual review of code. The sample code snippet below.
char *p = new char[size];
// use the pointer
delete p; <---- MEMORY LEAK
I was wondering why UMDH didn't catch this ? UMDH never reported this as an issue in the comparison log. Would WinDbg heap commmands would have helped to point out the leak ?

Qt DBus registerService function call returns false on an embedded Linux device

I’m new to DBus, but I’m trying to use it in two Qt applications on an embedded device. I have a very simple interface that consists of one slot:
QString SendMessage(const QString &cmd);
The server application is then using the following code to start the connection:
DbusService* dBus = new DbusService;
new interfaceIfAdaptor(dBus);
QDBusConnection connection = QDBusConnection::sessionBus();
bool ret = connection.registerService("com.domain.project.interface");
qDebug() << "returns" << ret;
ret = connection.registerObject("/", dBus);
qDebug() << "returns" << ret;
This works fine on the desktop. In the embedded system, the connection.registerService function returns false. As a result, any messages to the server fail. I’m not sure why. Running ‘ps’ tells me that [dbus-daemon —system] and [dbus-daemon —sesson] are both running.
Finally, I have noticed that Qt Creator complains when I debug the application. I see the following warning messages:
Could not load shared library symbols for 10 libraries, e.g. /opt/arm/lib/libQtDBus.so.4.
Use the “info sharedlibrary” command to see the complete listing.
Do you need “set solib-search-path” or “set sysroot”?
Could not load shared library symbols for /usr/lib/libdbus-1.so.3.
Do you need “set solib-search-path” or “set sysroot”?
If additional information is required to debug this problem, please let me know. Or if there are useful dbus commands I could run to help figure this out. Thanks!
It turns out the session bus was not getting started on the device. I enabled it, but then I ran into the problem of the address not getting propagated to the environment variables. I can manually set it in a terminal, but I'm not sure how to do the same in Qt Creator.
Anyway, rather than spend more time figuring out the issues with the session bus, I switched to using the system bus. I just had to change the /etc/dbus-1/system.conf file to allow anyone to talk to the system bus and my applications work on the embedded device. I know that's probably not the long term solution, but it works for now.

Continuous uploading causes QNetworkReply error "Cannot allocate memory"

I have an Qt application for symbian that receives gps data, stores it into a database and tries to post it to a server. First two steps work fine but continuous posting either crashes my application or kills my internet connection.
I have modified my application for debugging purposes so it only does post data to a server in every 10th second. Application runs fine for about 45-90min without any significant memory increase.
After that that I'll get an error from QNetworkReply saying "Cannot allocate memory".
Same time memory usage increases approximately 63500(bytes?).
On next upload I'll get reply that says "Invalid socket descriptor" and after that my QtCreator debug output is filled with "exception on 7 [will do setdefaultif(0) - hack]"
Anyone know what is going wrong here? I can't find errors from my upload code that could be causing this.
Here is my upload script.
void MainWindow::upload() {
//Content of postData below. Using same data on every upload now when tracking the bug
//[{"timestamp":"2010-10-01T17:10:27","latitude":62.1823321,"longitude":25.73226825,"user":6}]
QByteArray postData;
QNetworkRequest request;
request.setUrl(uploadUrl);
this->qnam->post(request, postData);
}
void MainWindow::serviceRequestFinished(QNetworkReply* reply) {
QByteArray bytes = reply->readAll();
if (reply->error() == QNetworkReply::NoError)
{
//nothing in here when debugging
} else {
qDebug() << "-------Reply error: " + reply->errorString();
}
reply->deleteLater();
updateHeapStats();
}
void MainWindow::updateHeapStats() {
#ifdef Q_OS_SYMBIAN
TInt mem, size, limit;
User::Heap().AllocSize(mem);
size = User::Heap().Size();
limit = User::Heap().MaxLength();
qDebug() << "**DEBUG MEMORY - > Memory: " << QString::number(mem);
qDebug() << "**DEBUG MEMORY - > Heap limit: " << QString::number(limit);
qDebug() << "**DEBUG MEMORY - > Heap size: " << QString::number(size);
#endif
}
Allmost forgot, I have tested this with Nokia N97mini, 5230 and 5800 and they all behave same way.
edit. Forgot to mention that when internet connection "dies" I still can see that 3G is on but connecting to internet with web-browser fails. When I close the application and try to connect to internet with browser it says "Web: Memory full, ..."(web requests from apps works fine) I'm using Nokia Energy profiler and it doesn't show any signs of memory being full. Even tested this and started 2 games, ovi maps and tons of other applications and they worked fine even though they consumed over 40MB of memory.
With the caveat that the only networking code I do in Qt is on a desktop platform and even then I need to look it up, I don't see anything obvious. I also know that in my own code deletelater() sometimes has a different idea of what "later" is than I do. I don't have time to look it up and may be wrong here, but I think deletelater() actually runs on the event thread, and if your event thread is always busy, when will it have time to delete the object? For debug purposes, I would replace deletelater() with delete (and really, there's no reason to use deletelater() unless you've got a parent/child relationship that you need to clean up, and there might be a way to manually remove the child from the parent so you don't need to worry about dangling pointers when you call delete).
I also don't know the accuracy of your memory consumption test. Does the allocated memory test refer to the current thread? The current process? Does a program received a "chunk" of memory from the heap that it simply managers on its own and it isn't permitted to use more than? I think you know this framework much better than I do; these are just some thoughts for you to try.

Resources