Details
-
Suggestion
-
Resolution: Done
-
Not Evaluated
-
5.2.1, 5.3.0
-
None
-
76e3365e3b0bc11a4766b4154fe46ad3dcf91251
Description
QSerialPort::~QSerialPort() helpfully calls QSerialPort::close() to ensure the serial port is not in use anymore. close() in turn emits an error [1] if it is called when it's already closed. This results in an error every time a QSerialPort is destroyed which has never been open()'ed or has already been close()'d manually.
This wouldn't be much of a problem as the object is destroyed anyway, but it does emit a signal in the process. This signal can be inconvenient as it is emitted during a destructor call: If a class Foo has a QSerialPort instance as a member and has a slot connected to the QSerialPort::SerialPortError signal, the slot is called after the Foo's destructor. This can cause some mayhem as Foo is already destroyed.
See attached code for an example.
I propose a simple fix for the solution: don't call close() in the destructor if the port is already closed.
E.g. in [2], instead of
QSerialPort::~QSerialPort()
{ close(); delete d_ptr; }use this
QSerialPort::~QSerialPort()
{ if (this->isOpen()) close(); delete d_ptr; }To summarize:
1. an object Foo derived from QObject and having an instance of QSerialPort is destroyed
2. Foo::~Foo() is called, Foo gets destroyed
3. QSerialPort::~QSerialPort() is called and calls QSerialPort::close()
4. QSerialPort::close() emits an error signal because it is already closed
5. The problem: This signal may now call Foo::someslot() even tough Foo was already destroyed in step 2
6. all members of Foo are destroyed, now it's ancestors are destroyed: QObject::~QObject() is called and disconnects all its signals and slots
Normally, a signal will never call a slot of a destroyed object as QObject::~QObject() will disconnect a destroyed object, but the destructor of a parent class is called after the destructor of the members of the class.