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. serialthing.h
          0.4 kB
        2. serialthing.cpp
          0.7 kB
        3. SerialPortCrash.pro
          0.4 kB
        4. main.cpp
          0.1 kB
        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