QObject based class has a queued connection to itself - qt

I was digging into some source code I am working on. I found a peculiar statement that someone had coded. The source code is a GUI application with a QML GUI and uses QT 4.7.x.
The snippet below belongs to core application logic.
// connect signal-slots for decoupling
QObject::connect (this, SIGNAL(setCurrentTaskSignal(int)), this,
SLOT(SetCurrentTaskSlot(int)), Qt::QueuedConnection);
It's strange that the object connects to itself via a queued connection which essentially means that the object may "live" in different threads at the same time?
At first glance It didn't made any sense to me. Can anyone think of any reason why such a connection would be plausible or needed?. Would this even work?

It will work without any problem. Maybe there was some event loop processing required before calling SetCurrentTaskSlot?
Note that QueuedConnection doesn't mean that something is in different thread. QueuedConnection means only that when signal is emitted, corresponding slot won't be called directly. It will be queued on event loop, and will be processed when control will be given back to event loop

The queued connection implies nothing about where the receiver lives. The opposite is true: to safely send signals to an object living in another thread, you must use queued connections. But you can use them for an object living in any thread!
One uses a queued connection to ensure that the signal will be delivered from within the event loop, and not immediately from the emit site as happens with direct connection. Direct connection is conceptually a set of calls to function pointers on a list. Queued connection is conceptually an event sent to a clever receiver who can execute a function call based on the contents of the event.
The event is the internal QMetaCallEvent, and it is QObject::event that acts upon this event and executes the call.

Related

QObject destructors not being called

I have two QObject child classes in my Qt application. One object from each of these classes was instantiated on the stack. Previously, my application would exit cleanly. However, since I've updated to Qt5.1.0, their destructors are not being called. I get the following warning twice when I launch the debugger.
the debug information found in "/usr/lib/debug//lib64/libfreebl3.so.debug"
does not match "/lib64/libfreebl3.so" (CRC mismatch)
Is this a bug in Qt or in my code?
See the documentation of QCoreApplication::exec:
We recommend that you connect clean-up code to the aboutToQuit() signal, instead of putting it in your application's main() function because on some platforms the QCoreApplication::exec() call may not return. For example, on Windows when the user logs off, the system terminates the process after Qt closes all top-level windows. Hence, there is no guarantee that the application will have time to exit its event loop and execute code at the end of the main() function after the QCoreApplication::exec() call.
You're using it incorrectly. It is not guaranteed that exec will be terminated after windows are closed. You should use aboutToQuit signal to stop other threads. If this signal is not emitted either, you need to call QApplication::quit() explicitly when your window is closed.
I'm not exactly sure in this case if this is a bug in your code or not, but anyway it is not recommended to create QObjects in the stack.
The reason is that the parent object (if any) will automatically call delete when destroyed, but then the object will also be automatically destroyed when it goes out of scope. Hence the object is destroyed twice which is Undefined Behaviour. That may explained why it worked well in one case, and not in another, since you can't rely on any consistent behaviour.
(But in your case it is weird that you say the destructor is not called at all...)

Can you call signal() from within a signal handler?

I have a supervisor program that generally wants to receive SIGCHLD events. However, after it receives SIGTERM or similar signal, it would be safe and desirable to ignore SIGCHLD events to prevent zombies. The issue is that I'm not sure if it's legal to call signal(2) when already inside a signal handler, so that e.g. SIGTERM calls signal(SIGCHLD, SIG_IGN). It doesn't appear to cause problems, but I know there are many restrictions placed on what you can do in a signal handler, and I'm unable to figure out whether calling signal is in the forbidden zone.
So: is this legal, reliably? If not, is there an alternative way to make sure that no children still running at the time of the SIGTERM can possibly zombie, even if they aren't properly waited on?
For Linux, look at the manpage for signal(7). There is a list of async-signal-safe functions. It says:
POSIX.1-2004 (also known as POSIX.1-2001 Technical Corrigendum 2) requires an implementation to guarantee that the following functions can be safely called inside a signal handler:
signal() is in the list. So it's safe.

Understanding how netty works

I'm trying to understand how netty works, and after reading some of the documentation I was to see if I understood how things work at a high level.
Basically netty has an event cycle, so whenever you make a call it gets serialized and the request gets pushed down to the o/s level, and it uses epoll and waits for an event to send back to netty.
When the operation system generates an event that netty subscribed to, netty then has an event loop that gets triggered.
Now the interested part here is, the event that gets triggered has to be parsed, and the client code (or custom code) has to figure out who actually this event is for.
So for example, if this was for a chat application, when a message is sent, it is up to the client code to figure out to send this message via ajax to the correct user.
Is this, at a high level, a correct overview of how netty works?
BTW, when netty listens for events sent via epoll, is this event loop single threaded or does it work from a pool of threads?
Sounds correct to me.
There are more than one event loop thread in Netty, but it does not mean a single Channel's event is handled by multiple event loop threads. Netty picks one thread and assigns it to a Channel. Once assigned, all events related with the Channel is handled by the picked thread.
It does not also necessarily mean that an event loop thread handles only one Channel. An event loop thread can handle multiple Channels.

Qt 4.7 Emitting a signal to a specific thread

I have several client GUI windows all derived from QMainWindow. Each window is potentially doing a different task but all are requesting data from a central cache implemented as a QThread.
All the clients connect to the same slot in the data cache and then emit signals to prompt the data cache to do something. The signals to the data cache get queued so the data cache only ever does one thing at a time.
When the data cache completes it needs to inform the correct client that the thing it was doing has completed. My immediate thought is to emit a signal to the requesting client about the completion. This would mean connecting to a specific client's slot and then emitting a signal to it.
Do I have to do connect and then disconnect to the client? I'm aware of the QObject::sender() function to get the supplier. Is there some way of emitting a signal to that sender (client) only? Or is there some other way of doing this?
There may be simpler approaches you can take to resolve your problem. For example, I would consider looking into the QtConcurrent framework. Alternately, you might also re-architect your design such that the client first connects to a "finished" signal on the cache prior to asking the cache to do anything. Failing all of that, you might also consider relying on the QMetaObject::invokeMethod function (for either your client or your cache). This function allows you to call an arbitrary method on an arbitrary QObject (provided that you have a pointer to it) using arbitrary generic arguments (in a way that's thread-safe).
If you use the QMetaObject::invokeMethod approach, there are a few of drawbacks you should be aware of. Firstly, you have to invoke the method using its string name, which means that you won't find out at compile time if you're using the wrong name. Secondly, since your clients have a different thread affinity than the central cache, there's a chance that the client will have been destroyed when the cache invokes the method on them (though perhaps in your case, this won't be a problem for you). Finally, you may not want your cache to have any knowledge of the names of the methods that it must execute on its client.
I don't have any way of getting around the first drawback (I'm not sure if this is going to be handled differently in the upcoming Qt 5.0 release). As far as the second and third problems, I would recommend creating an object that encapsulates a reference to a method -- something like the following:
class MethodReference
{
MethodReference(QObject* object, const QString& methodName);
...
bool invoke(QGenericArgument val0 = QGenericArgument(),
QGenericArgument val1 = QGenericArgument(),
...
QGenericArgument val9 = QGenericArgument());
private:
QPointer<QObject> mObject;
QString mMethod;
};
You would then pass this object to your cache from the client. The cache then calls invoke on this object.
Note the use of QPointer -- this gives you a thread-safe way of checking if your object has been destroyed before you try to invoke a method on it. Since I've done this before, I'll also let you know that versions of Qt prior to 4.8 had a bug in QPointer that would cause a crash in a multi-threaded context. Use a more recent version of Qt if you want to do this.
I hope this was clear.

Registering for RConnectionMonitor events causes thread to panic

I have a custom observer class derived from CBase, MConnectionMonitorObserver, and QObject(for signals) that I use to observe events from RConnectionMonitor.
When I call the RConnectionMonitor::NotifyEventL passing the observer instance, the application crashes saying that a thread has panicked.
What I'm trying to do here is to listen to the network events asynchronously without blocking the main thread.
EDIT: Should I use an active object to hold the RConnectionMonitor object?
Best regards
The problem was, as #James commented, that I was registering for events before I established the connection to the connection monitor server.

Resources