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

Exception raised when trying to perform a new ModBus connection after a connection loss

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P1: Critical
    • Resolution: Invalid
    • Affects Version/s: 5.9.0, 5.9.1
    • Fix Version/s: None
    • Labels:
    • Environment:
      Using Qt Creator 4.3.1 under Windows 10.

      Tested with 5.8 MinGW, 5.9.0 MinGW 32bits and MSVC2017 64bits, 5.9.1 MinGW and MSVC2017 64bits, and 5.10 alpha MSVC2017 64bits builds.
    • Platform/s:
      Windows
    • Story Points:
      13
    • Sprint:
      Qt6_Foundation_Sprint 29

      Description

      In a master ModBus application using a RS485 USB adapter, if the connection is lost, the current QModbusDevice connection is closed and destroyed and a new one is created. When performing the new "connectDevice()" call, an exception is raised (see attached files) if the connection is lost when the remote slave board is disconnected or powered off.

      This issue doesn't occur if the connection is lost by disconnecting the USB adapter.

       I cannot give you all the project source code but here is the slot function where the issue occurs at the "if (!modbusMaster->connectDevice())" line:

      /**
       * This slot is connected to the timeout event of the QTimer configured in the
       * constructor of the class.
       *
       * It is used to read periodically the new values of the input registers of
       * the board or to reset the Modbus connection in case of a false reply
       * timeout which can occurs with some RS485 USB controllers.
       *
       * If a connection reset is requested after the first reply, we assume there is
       * no board connected on the current serial port and we close the
       * connection.
       */
      void Nitroxychrom::readAllInputRegisters() {
          if (!resetConnection) {
              QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::InputRegisters, 0, MODBUS_INPUT_REG_NUMBER);
              QModbusReply *reply = modbusMaster->sendReadRequest(request, 2);
      
              if (!reply->isFinished()) {
                  connect(reply, &QModbusReply::finished, this, &Nitroxychrom::replyReady);
              } else {
                  parseReply(reply);
              }
          } else {
              resetConnection = false;
      
              timer->stop();
              modbusMaster->disconnectDevice();
              delete modbusMaster;
              modbusMaster = nullptr;
      
              if (firstRead) {
                  // There is no connected CPREG-N2 board or it doesn't reply the proper data
                  ui->serialPortListBox->setEnabled(true);
                  ui->serialPortListRefreshButton->setEnabled(true);
                  ui->connectButton->setText(tr("Connect"));
      
                  setConnectionState(ConnectionState::Error);
              } else {
                  // Performing the new connection
                  modbusMaster = new QModbusRtuSerialMaster(this);
                  modbusMaster->setConnectionParameter(QModbusDevice::SerialPortNameParameter, ui->serialPortListBox->currentText());
                  modbusMaster->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);
                  modbusMaster->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600);
                  modbusMaster->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
                  modbusMaster->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
                  modbusMaster->setTimeout(1000);
                  modbusMaster->setNumberOfRetries(3);
      
                  connect(modbusMaster, &QModbusRtuSerialMaster::stateChanged, this, &Nitroxychrom::modbusStateChanged);
      
                  if (!modbusMaster->connectDevice()) {
                      delete modbusMaster;
                      modbusMaster = nullptr;
      
                      ui->serialPortListBox->setEnabled(true);
                      ui->serialPortListRefreshButton->setEnabled(true);
                      ui->connectButton->setText(tr("Connect"));
      
                      setConnectionState(ConnectionState::TimeOut);
                  }
              }
          }
      }
      

      This issue only exists since 5.9.x and is still present in the latest 5.10 alpha preview. No issue at all with the 5.8 version.

      It may concers the MobBus and/or the Serial Port module by looking at the stack.

        Attachments

        1. mainwindow.cpp
          5 kB
        2. mingw_exception_stack.txt
          4 kB
        3. mingw_exception_warning.png
          mingw_exception_warning.png
          5 kB
        4. Modbus-Bug-QtCreator-Project.zip
          8 kB
        5. modbus-bug-virtualcom.png
          modbus-bug-virtualcom.png
          141 kB
        6. msvc_exception_stack.txt
          7 kB
        7. msvc_exception_warning.png
          msvc_exception_warning.png
          6 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

            Assignee:
            heimrich Karsten Heimrich
            Reporter:
            herve Herve Spitz
            PM Owner:
            Maurice Kalinowski Maurice Kalinowski
            RnD Owner:
            Alex Blasche Alex Blasche
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:

                Gerrit Reviews

                There are no open Gerrit changes