Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-39369

QSerialPort emits error in destructor

    XMLWordPrintable

    Details

    • Type: Suggestion
    • Status: Closed
    • Priority: Not Evaluated
    • Resolution: Done
    • Affects Version/s: 5.2.1, 5.3.0
    • Fix Version/s: 5.3.1
    • Component/s: Serial Port
    • Labels:
      None
    • Commits:
      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.

      [1] https://qt.gitorious.org/qt/qtserialport/source/04a3308346190a70509a759423993f6bcc365328:src/serialport/qserialport.cpp#L564-1371

      [2] https://qt.gitorious.org/qt/qtserialport/source/04a3308346190a70509a759423993f6bcc365328:src/serialport/qserialport.cpp#L425-1371

        Attachments

        1. main.cpp
          0.1 kB
          Samuel Bryner
        2. SerialPortCrash.pro
          0.4 kB
          Samuel Bryner
        3. serialthing.cpp
          0.7 kB
          Samuel Bryner
        4. serialthing.h
          0.4 kB
          Samuel Bryner
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

            Assignee:
            iliis Samuel Bryner
            Reporter:
            iliis Samuel Bryner
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:

                Gerrit Reviews

                There are no open Gerrit changes