Ian Medeiros
Ian Medeiros

Reputation: 1776

Is there any possibility to throw an exception when emitting a Qt signal?

While reviewing some code, I found a piece of code like that:

struct MyFooStructure
{
  //Nothing unusual, just basic types
}

class Foo : public QObject
{
   Q_Object

public:
   void fooMethod(const MyStructure &s);

signals:
   void fooSignal(const MyStructure &);
}

void Foo::fooMethod(const MyStructure &s)
{
   try
   {
      emit fooSignal(s)
   }
   catch(const std::exception &e)
   {
      qDebug() << "An exception!";
   }
}

Is there any possibility to enter on the catch here? As far as I know, there are no possible exception being thrown: emit is just a macro to create a table to call the appropriate functions connected to that signal on the *.moc file. Is that try catch really needed?

Upvotes: 3

Views: 1832

Answers (1)

Thomas McGuire
Thomas McGuire

Reputation: 5466

Yes, the catch is needed in your example, at least if any slots connected to fooSignal throw an std::exception.

The statement emit fooSignal(); calls all connected slots synchronously. Basically QObject internally has a connection table in which it stores all connections for an object, which each slot being a function pointer. Basically what emit does (or rather, what the moc-generated implementation of fooSignal does) is that it simply iterates over the connection table and calls all function pointers for each connected slot.

So the slots are called from within the connect statement. That also means if any slots throw an exception, the exception will propagate outside of the emit statement.

Note that the internal moc-generated code for fooSignal is only exception-safe as of recent, see Olivier's answer on this bug report. That means older versions of Qt can't deal with exceptions being thrown in slots, and the moc-generated code will fail in undefined ways if slots throw an exception.

EDIT: I also want to add that having slots that throw exceptions is bad practice, try avoiding that. The code that calls emit doesn't know what slots are connected, so it doesn't know what exceptions it needs to catch. Furthermore, as soon as you have queued connections instead of direct connections, the slots will be called asynchronously instead of synchronously, and you won't be able to catch the slots' exceptions.

Upvotes: 6

Related Questions