An annoying problem about QSerialPort usage



  • Hello everyone, I have a strange problem, I design a application, one part of code of this project like following:
    @
    while(serialPort->waitForReadyRead(30))
    {
    DataReceive = serialPort->readAll();
    ReceiveData.append(DataReceive);
    }
    @
    The strange problem is sometimes my application could work well, but sometimes It would show "SIGSEGV, Segmentation fault" at
    @
    DataReceive = serialPort->readAll();
    @
    My application run same code, but sometime would be failed.And does Qt provide debug tool?? Because when I receive "SIGSEGV, Segmentation fault", I had no idea with this.
    Thanks in advance.


  • Moderators

    According to the name you are using for your instance it is serial communication. Possibly readAll is wrongly reimplemented or not fully compatible with QtSerialPort.

    Certainly it is very convenient to use readAll. However, you may want to try "readData":http://qt-project.org/doc/qt-5.0/qtcore/qfiledevice.html#readData with size instead. At least it is the next logical thing to try. Otherwise you might want to file a bug report on "JIRA":https://bugreports.qt-project.org/secure/Dashboard.jspa.

    Note: I have not used QtSerialPort yet.
    2nd: A more sensible thread title would help as well. If you are using QtSerialPort and putting this into the title of your thread will probably trigger the original contributor (kuzi... something is his name) to read your thread and provide help.



  • When I use serialPort->readData(), I got a error from Compiler, it told me this function is protected.Thus, I use serialPort->read(), it would still happened same thing I mentioned before.Is this really a bug??Or I forget something??I have double-checked my code, I didn't find anything would change my memory.......



  • Hi guys. I'm here. :)

    Ivan,

    1. What OS is used?
    2. What serial chip/model is used?
    3. Please give the minimum console example which reproduces this problem.
    4. Still I don't recommend to use waitForXX() methods. Use non-blocking approach instead of the blocking.
    5. Mr. Koahning mean use just read() method instead of readAll(). Try and let know about results.


  • Ivan,

    1. Check that you allocate memory for DataReceive with safe size:

    char* DataReceive = new char(maxsize);

    1. Check for building object serialPort befor using it.

    good luck



  • Hello, Thanks for reply

    1)My OS is Windows 7

    1. It's a USB Serial Port

    3)Following is my code that error always happened here
    @
    serialPort->clear();
    ReceiveData.clear();
    serialPort->write(requestData);
    serialPort->flush();
    if( requestCmd == MemoryAccess)
    {
    for( i =0; i< 70; i++)
    {
    while(serialPort->waitForReadyRead(30))
    {
    DataReceive = serialPort->read(50)
    ReceiveData.append(DataReceive);
    }
    if(ReceiveData.length() !=0)
    break;
    }
    }
    @

    4)Because I found document on Qt website, It showed this method that I could use.Does non-blocking mean like following code
    @
    connect(serialPort,readyRead(),&myobject,receiveData())
    @

    5)Yes, I tried. But I got same result that sometime fault would be occured.



  • Hi, mehrdadsilver
    "DataReceive" is QByteArray, I didn't use pointer, so It absolutely is initialized and had enough place."serialPort" is initialized in the constructor of my class, so I believed It was used after I initialized it.The strangest thing is sometimes my application run correctly and got correct result, but sometime I would get error message like "segmentation fault".



  • Please provide an minimal separate console project (with an simple read/write operations) which reproduces this problem. Instead of a piece of a code from your current project. Because you can have a error somewhere in a your code of your project.



  • I don't know what "minimal separate console project" means..., I could e-mail the project to you.



  • I require the minimal console project (without GUI) with source files, which I can recompile and run on the my side.

    Project should contain an pro file, and *.h, *cpp files with a class with your I/O.

    Should be used a methods: serialPort->clear(), serialPort->write(), serialPort->flush(), serialPort->waitForReadyRead(), serialPort->read(). That's all.

    If you by means of this "console project" successfully to reproduce SEGFAILT, then a problem in QtSerialPort. If it isn't possible to reproduce - that a problem somewhere at your code of your main project.



  • I thought if i step by step to read or write data through QtSerialPort, that would no error happen. I proved it before. My project is for company, because we want to flash memory of product through comport, it would frequently in a short time to write or read data massively.And sometime it is successful, sometime it's failed.If you don't have related product, even though I gave you the sample code, you still can't have same situation like mine.



  • Please provide an minimal project with I/O. That's it.


  • Moderators

    [quote author="kuzulis" date="1378888607"]Hi guys. I'm here. :)

    Ivan,

    1. What OS is used?
    2. What serial chip/model is used?
    3. Please give the minimum console example which reproduces this problem.
    4. Still I don't recommend to use waitForXX() methods. Use non-blocking approach instead of the blocking.
    5. Mr. Koahning mean use just read() method instead of readAll(). Try and let know about results. [/quote]

    Thanks a lot for picking up the discussion.
    Using SerialPort in the title line seems to work very quick ;-)
    Sorry, that I could not remember your name.



  • Ivan, Can you e-mail for me your project?



  • Sure, but i need your e-mail address.



  • Hi, I simplify my code like following, please check:

    pro file
    @
    QT += core serialport

    QT -= gui

    TARGET = QSerialPortDebug
    CONFIG += console
    CONFIG -= app_bundle

    TEMPLATE = app

    SOURCES += main.cpp
    worker.cpp

    HEADERS +=
    worker.h

    @

    worker.h
    @
    #ifndef WORKER_H
    #define WORKER_H

    #include <QObject>
    #include <QFile>
    #include <QtSerialPort/QSerialPort>
    #include <QtSerialPort/QSerialPortInfo>

    class worker : public QObject
    {
    Q_OBJECT
    public:
    explicit worker(QObject *parent = 0);
    QFile file;
    QSerialPort *serialPort;
    QList<QSerialPortInfo> SerialInfo;
    QByteArray readData;
    QByteArray ReceiveData;
    QString sendData;
    void InitialComport();

    signals:

    public slots:

    };

    #endif // WORKER_H
    @

    worker.cpp
    @
    #include "worker.h"

    worker::worker(QObject *parent) :
    QObject(parent)
    {
    serialPort = new QSerialPort();
    InitialComport();
    file.setFileName("Image.hex");
    }
    void worker::InitialComport()
    {
    SerialInfo = QSerialPortInfo::availablePorts();
    serialPort->setPort(SerialInfo[0]);
    serialPort->open(QSerialPort::ReadWrite);
    serialPort->setBaudRate(QSerialPort::Baud38400);
    serialPort->setDataBits(QSerialPort::Data8);
    serialPort->setStopBits(QSerialPort::OneStop);
    serialPort->setParity(QSerialPort::NoParity);
    }

    @

    main.cpp
    @
    #include <QCoreApplication>
    #include <QThread>
    #include <worker.h>
    #include <QTextStream>
    #include <QDebug>
    using namespace std;
    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);
    worker WORKER;
    WORKER.file.open(QIODevice::ReadWrite);
    QTextStream Image(&WORKER.file);
    while (Image.atEnd()) {
    WORKER.sendData = Image.readLine();
    WORKER.serialPort->write(WORKER.sendData.toLocal8Bit());
    for(int i = 0; i <30; i++)
    {
    while(WORKER.serialPort->waitForReadyRead(35))
    {
    WORKER.ReceiveData = WORKER.serialPort->read(50);
    }
    if(WORKER.ReceiveData.length() != 0)
    break;
    }
    qDebug() << QString(WORKER.ReceiveData);
    WORKER.ReceiveData.clear();
    }
    WORKER.serialPort->close();
    return a.exec();
    }

    @



  • I'm sorry, but your example is incorrect.

    I used the yourself a loopback example with use "Com0Com":http://sourceforge.net/projects/com0com/

    Emulation of baud rate in Com0Com has to be enabled.

    I used two Flasher and Eeprom applications to your I/O emulation.

    Flasher:

    (main.cpp)

    [code]
    #include <QCoreApplication>
    #include <QFile>
    #include <QElapsedTimer>
    #include <QDebug>
    #include <qserialport.h>

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    QSerialPort serialPort;
    serialPort.setPortName("COM4");
    bool ret = serialPort.open(QSerialPort::ReadWrite)
            && serialPort.setBaudRate(QSerialPort::Baud38400)
            && serialPort.setDataBits(QSerialPort::Data8)
            && serialPort.setStopBits(QSerialPort::OneStop)
            && serialPort.setParity(QSerialPort::NoParity);
    qDebug() << "serial port: " << ret;
    
    QFile sourceHexImage("path/to/source/image/src.hex");
    ret = sourceHexImage.open(QIODevice::ReadOnly);
    qDebug() << "source image ret: " << ret;
    
    QFile destinationHexImage("path/to/destination/image/dst.hex");
    ret = destinationHexImage.open(QIODevice::WriteOnly | QIODevice::Truncate);
    qDebug() << "destination image ret: " << ret;
    
    QElapsedTimer timer;
    timer.start();
    
    const int ioChunkSize = 25; // bytes
    const int waitTimeout = 35; // msec
    
    while (!sourceHexImage.atEnd()) {
        QByteArray chunk = sourceHexImage.read(ioChunkSize);
        serialPort.write(chunk);
        ret = serialPort.flush();
        while (serialPort.waitForReadyRead(waitTimeout)) {
            if (serialPort.bytesAvailable() == ioChunkSize)
                break;
        }
        chunk = serialPort.read(ioChunkSize);
        destinationHexImage.write(chunk);
    }
    
    serialPort.close();
    sourceHexImage.close();
    destinationHexImage.close();
    
    qDebug() << timer.elapsed() << "msec, done...";
    
    return a.exec&#40;&#41;;
    

    }
    [/code]

    Eeprom emulator - Echo application

    (main.cpp)

    [code]
    #include <QCoreApplication>

    #include "echo.h"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);
    Echo echo;
    echo.init();
    return a.exec();
    }
    [/code]

    (echo.h)

    [code]
    #ifndef ECHO_H
    #define ECHO_H

    #include <QDebug>
    #include <qserialport.h>

    class Echo : public QObject
    {
    Q_OBJECT
    public:
    explicit Echo(QObject *parent = 0 ) : QObject(parent) {
    connect(&serialPort, SIGNAL(readyRead()), this, SLOT(onEcho()));
    }

    bool init() {
        serialPort.setPortName("COM5");
        bool ret = serialPort.open(QSerialPort::ReadWrite)
                && serialPort.setBaudRate(QSerialPort::Baud38400)
                && serialPort.setDataBits(QSerialPort::Data8)
                && serialPort.setStopBits(QSerialPort::OneStop)
                && serialPort.setParity(QSerialPort::NoParity);
        return ret;
    }
    

    private slots:
    void onEcho() {
    const QByteArray data = serialPort.readAll();
    qDebug() << data;
    serialPort.write(data);
    }

    private:
    QSerialPort serialPort;
    };

    #endif // ECHO_H
    [/code]

    I have no SEGFAULT.



  • Thanks for your test.But actually when I receive packet from Comport, I need to collect complete packet that my program then could parse correctly, so I can't give the constant number that used on serialport->read().My original program for serialPort is run on another thread I created, because I want to show information on GUI. Does it make my program fail......, why sometimes my program could work, sometimes would crashed....., they run on same code.....



  • bq. But actually when I receive packet from Comport, I need to collect complete packet that my program then could parse correctly, so I can’t give the constant number that used on serialport->read().

    I'm too collect data up to 25 bytes. (ioChunkSize = 25).. And in principle, it makes no difference...

    bq. My original program for serialPort is run on another thread I created, because I want to show information on GUI.

    To avoid of potential errors - just use an non-blocking approach, it will be simple and more safely.



  • "non-blocking method" is you mentioned on "Eeprom emulator – Echo application" ??

    bq. I’m too collect data up to 25 bytes. (ioChunkSize = 25).. And in principle, it makes no difference…

    I mean I don't know how many bytes I should receive until I don't receive any data from serialPort.



  • bq. “non-blocking method” is you mentioned on “Eeprom emulator – Echo application” ??

    Yes.

    bq. I mean I don’t know how many bytes I should receive until I don’t receive any data from serialPort.

    I know that you mean. In an example which I gave, 25 bytes it is simple an example. My example is used for trying to detect of crash in case of the intensive I/O.



  • I still think there is a problem inside, could you try using QtserialPort with a Qthread??



  • bq. could you try using QtserialPort with a Qthread??

    You can use as well QThread.

    But I have no free time on detection of your crash and I can't reproduce your crash.

    Please give for me an simple projects with emulation of Flasher & Eeprom with use Com0Com which reproduce a problem. Because in other case, I can't help to you because I do not have an your Hardware.

    Or, you should do it yourself. For testing and debugging you have to download source codes of QtSerialPort and include them to the project directly through the *.pri file.

    E.g., ourproject.pro :
    [code]
    QT += core
    QT -= gui
    TARGET = ourproject
    CONFIG += console
    CONFIG -= app_bundle
    TEMPLATE = app

    include(path/to/serialport-lib.pri)

    SOURCES += oursources.cpp
    HEADERS += ourheaders.h
    [/code]

    Of course, it is necessary to fix some errors when compilation, by some modification of the QtSerialPort files. It will allow you to receive a call-stack and to detect a cause of crash.



  • Thank you very much : ).


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.