Get sigabrt exception when I try to send data using QTcpSocket to InfluxDB
-
Provide some code or even better a testcase.
For me it looks like you either access data from two different threads without proper locking or access the socket from two different threads.Why do you have such a strange time constraint on the main thread?
@Christian-Ehrlicher
As I said, Its a real-time application. We have time-critical tools running on production floor. It could damage the products in case the main thread gets blocked.Let me try to write some sample code and try to create similar scenario. Will post some code soon.
Thanks,
Amit -
Hello Friends,
Sorry for the delay.
I have attached the code which creates similar scenario of my application. Instead of GUI, our application is a service which has infinitely running main thread. Since It is time-critical application, every function has to be completed in less than 20 milliseconds.#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); socket = new QTcpSocket(this); timer = new QTimer(this); timer->setInterval(20); tcpThread = new QThread(this); connect(socket, SIGNAL(connected()),this, SLOT(connected())); connect(socket, SIGNAL(disconnected()),this, SLOT(disconnected())); connect(socket, SIGNAL(readyRead()),this, SLOT(readyRead())); QObject::connect(timer, SIGNAL(timeout()), this, SLOT(SendData())); socket->moveToThread(tcpThread); doConnect(); tcpThread->start(); header = QByteArray("POST /api/v2/write?org=ABC&bucket=AAA&precision=ns HTTP/1.1\r\nHost: localhost:8086\r\nAuthorization: Token UtUW9twti\r\nContent-Type: application/vnd.flux; charset=utf-8\r\nContent-Length: "); } MainWindow::~MainWindow() { tcpThread->quit(); timer->stop(); socket->disconnect(); delete tcpThread; delete socket; delete timer; delete ui; } void MainWindow::connected() { qDebug() << "connected..."; } void MainWindow::doConnect() { qDebug() << "connecting..."; // this is not blocking call socket->connectToHost(QString::fromLocal8Bit("localhost"), 8086); if(!socket->waitForConnected(5000)) { // we need to wait... << "Error: " << socket->errorString(); } } void MainWindow::readyRead() { qDebug() << "reading..."; // read the data from the socket auto rep = socket->readAll(); qDebug() << rep; if(rep.contains("400") && rep.contains("Connection: close")) { qDebug() << "Connection: Closed >>"; } } void MainWindow::disconnected() { qDebug() << "disconnected..."; } void MainWindow::on_pushButton_clicked() { timer->start(20); } QByteArray MainWindow::CollectData() { //This function collect data from various parts of the tool at real-time. QByteArray("Data, Tool=A, temp=200,X=40,Y=20.5,Z=8.8"); } void MainWindow::SendData() { QByteArray infline = CollectData(); if(socket->isOpen()) { auto res = socket->write(header + QByteArray::number(infline.length()) + "\r\n\r\n"); res = socket->write(infline); } }I ran more test on my application and got more meaning-full error trace this time. Clearly it has something to do with Write & Read operations. I know, QAbstractSocket class is not thread safe. Is it a synchronisation issue? Is there anything else causing problem? Can somebody please help?
Caught SIGABRT
/opt/bin/test(+0x395ce) [0x55beea4995ce]
/lib/x86_64-linux-gnu/libc.so.6(+0x43090) [0x7f0108c86090]
/lib/x86_64-linux-gnu/libc.so.6(gsignal+0xcb) [0x7f0108c8600b]
/lib/x86_64-linux-gnu/libc.so.6(abort+0x12b) [0x7f0108c65859]
/lib/x86_64-linux-gnu/libc.so.6(+0x8d26e) [0x7f0108cd026e]
/lib/x86_64-linux-gnu/libc.so.6(+0x952fc) [0x7f0108cd82fc]
/lib/x86_64-linux-gnu/libc.so.6(+0x9596b) [0x7f0108cd896b]
/lib/x86_64-linux-gnu/libc.so.6(+0x96e8b) [0x7f0108cd9e8b]
/lib/x86_64-linux-gnu/libc.so.6(+0x98f22) [0x7f0108cdbf22]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x2d6) [0x7f0108cde156]
QByteArray::realloc(int)
QByteArray::resize(int)
QAbstractSocket::readData(char, long long)
QIODevice::read(char, long long)
QIODevice::readAll()**
test::threads::MasterThread::_writeToMapFile()
test::threads::MasterThread::writeDataToMapFile()
test::threads::MasterThread::process()
/opt/lib/libtest_core.so.1(+0x44e025) [0x7f010990e025]
/opt/lib/libQtCore-test.so.4(+0xab622) [0x7f01092be622]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x8609) [0x7f010903c609]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x43) [0x7f0108d62133]Regards,
Amit -
Hello Friends,
Sorry for the delay.
I have attached the code which creates similar scenario of my application. Instead of GUI, our application is a service which has infinitely running main thread. Since It is time-critical application, every function has to be completed in less than 20 milliseconds.#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); socket = new QTcpSocket(this); timer = new QTimer(this); timer->setInterval(20); tcpThread = new QThread(this); connect(socket, SIGNAL(connected()),this, SLOT(connected())); connect(socket, SIGNAL(disconnected()),this, SLOT(disconnected())); connect(socket, SIGNAL(readyRead()),this, SLOT(readyRead())); QObject::connect(timer, SIGNAL(timeout()), this, SLOT(SendData())); socket->moveToThread(tcpThread); doConnect(); tcpThread->start(); header = QByteArray("POST /api/v2/write?org=ABC&bucket=AAA&precision=ns HTTP/1.1\r\nHost: localhost:8086\r\nAuthorization: Token UtUW9twti\r\nContent-Type: application/vnd.flux; charset=utf-8\r\nContent-Length: "); } MainWindow::~MainWindow() { tcpThread->quit(); timer->stop(); socket->disconnect(); delete tcpThread; delete socket; delete timer; delete ui; } void MainWindow::connected() { qDebug() << "connected..."; } void MainWindow::doConnect() { qDebug() << "connecting..."; // this is not blocking call socket->connectToHost(QString::fromLocal8Bit("localhost"), 8086); if(!socket->waitForConnected(5000)) { // we need to wait... << "Error: " << socket->errorString(); } } void MainWindow::readyRead() { qDebug() << "reading..."; // read the data from the socket auto rep = socket->readAll(); qDebug() << rep; if(rep.contains("400") && rep.contains("Connection: close")) { qDebug() << "Connection: Closed >>"; } } void MainWindow::disconnected() { qDebug() << "disconnected..."; } void MainWindow::on_pushButton_clicked() { timer->start(20); } QByteArray MainWindow::CollectData() { //This function collect data from various parts of the tool at real-time. QByteArray("Data, Tool=A, temp=200,X=40,Y=20.5,Z=8.8"); } void MainWindow::SendData() { QByteArray infline = CollectData(); if(socket->isOpen()) { auto res = socket->write(header + QByteArray::number(infline.length()) + "\r\n\r\n"); res = socket->write(infline); } }I ran more test on my application and got more meaning-full error trace this time. Clearly it has something to do with Write & Read operations. I know, QAbstractSocket class is not thread safe. Is it a synchronisation issue? Is there anything else causing problem? Can somebody please help?
Caught SIGABRT
/opt/bin/test(+0x395ce) [0x55beea4995ce]
/lib/x86_64-linux-gnu/libc.so.6(+0x43090) [0x7f0108c86090]
/lib/x86_64-linux-gnu/libc.so.6(gsignal+0xcb) [0x7f0108c8600b]
/lib/x86_64-linux-gnu/libc.so.6(abort+0x12b) [0x7f0108c65859]
/lib/x86_64-linux-gnu/libc.so.6(+0x8d26e) [0x7f0108cd026e]
/lib/x86_64-linux-gnu/libc.so.6(+0x952fc) [0x7f0108cd82fc]
/lib/x86_64-linux-gnu/libc.so.6(+0x9596b) [0x7f0108cd896b]
/lib/x86_64-linux-gnu/libc.so.6(+0x96e8b) [0x7f0108cd9e8b]
/lib/x86_64-linux-gnu/libc.so.6(+0x98f22) [0x7f0108cdbf22]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x2d6) [0x7f0108cde156]
QByteArray::realloc(int)
QByteArray::resize(int)
QAbstractSocket::readData(char, long long)
QIODevice::read(char, long long)
QIODevice::readAll()**
test::threads::MasterThread::_writeToMapFile()
test::threads::MasterThread::writeDataToMapFile()
test::threads::MasterThread::process()
/opt/lib/libtest_core.so.1(+0x44e025) [0x7f010990e025]
/opt/lib/libQtCore-test.so.4(+0xab622) [0x7f01092be622]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x8609) [0x7f010903c609]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x43) [0x7f0108d62133]Regards,
Amit@AmitParmar
I don't know if this helps. What is yourtest::threads::MasterThreadstuff? If that is callingsocket->readAll()then, so far as I understand, that must only be called from the thread in whichsocketlives/has been moved to, i.e.tcpThread. Is that the case/not the case? -
Sorry for the confusion. The stack trace, I posted was from my actual application where as the code, I posted was the test code I wrote for creating same scenario to my actual application.
Here's the part of the code from my actual application. As you can see, MasterThread is main thread and m_influxDBThread is for sending/receiving data.
Hopefully, It gives more idea.
MasterThread::MasterThread(double interval) : BaseThread(new MasterThreadObject(this)), m_influxDBSocket(new QTcpSocket), m_influxDBThread(new QThread) { m_influxDBThread->start(); } void MasterThread::ReadyRead() { if(m_influxDBSocket->bytesAvailable() > 0) { m_resp = m_influxDBSocket->readAll(); if(m_resp.contains("400") || m_resp.contains("413") || m_resp.contains("429") || m_resp.contains("500") || m_resp.contains("503")) { qDebug() << "error"; } } } void MasterThread::_writeToMapFile() { m_influxDBSocket->write(m_influxDBHeader + QByteArray::number(len) + "\r\n\r\n"); foreach (const QByteArray &tag, m_influxDBLines.keys()) { QByteArray dataline = QByteArray(*m_influxDBLines.value(tag)); auto datalength = dataline.length(); if(datalength > 0) { long bytewritten = m_influxDBSocket->write(dataline); } } } bool MasterThread::setInfluxDB() { m_influxDBSocket->connectToHost(QString::fromLocal8Bit(host), port); if (!m_influxDBSocket->waitForConnected()) { return false; } m_influxDBSocket->moveToThread(m_influxDBThread); connect(m_influxDBSocket, SIGNAL(readyRead()), this, SLOT(ReadyRead()), Qt::DirectConnection); } -
Wrong yet.
You need to call the socket methods from that thread, where the socket lives.
You need to create the socket without of a parent , before moving to a thread.
To call the methods, you can use the invokeMethod function , or the signals/slots with the queued type.
To check that a method is called from the right thread, print the current thread id inside of a caller.
Or, do not use a threads without if a important reason.
-
Wrong yet.
You need to call the socket methods from that thread, where the socket lives.
You need to create the socket without of a parent , before moving to a thread.
To call the methods, you can use the invokeMethod function , or the signals/slots with the queued type.
To check that a method is called from the right thread, print the current thread id inside of a caller.
Or, do not use a threads without if a important reason.
@kuzulis said in Get sigabrt exception when I try to send data using QTcpSocket to InfluxDB:
You need to call the socket methods from that thread, where the socket lives.
For me it looks like you either access data from two different threads without proper locking or access the socket from two different threads.
Some people are simply not reading or ignoring the hints they were given... and then wonder when they get no answers anymore.
-
@kuzulis said in Get sigabrt exception when I try to send data using QTcpSocket to InfluxDB:
You need to call the socket methods from that thread, where the socket lives.
For me it looks like you either access data from two different threads without proper locking or access the socket from two different threads.
Some people are simply not reading or ignoring the hints they were given... and then wonder when they get no answers anymore.
Hey Chris,
I already got your point and understand your hints. I also found out QAbstractClass is not thread safe which seems culprit in this case but believe me, I already tried to run application by locking Read & Write operations with mutex so many times. It didnt work somehow.If you know any code or any test application which has similar scenarios, Could you please point me out? Sorry, I am not very good with QT framework.
Right now, I am trying to understand and implement, kuzulis's points into my application.
-
Hey Chris,
I already got your point and understand your hints. I also found out QAbstractClass is not thread safe which seems culprit in this case but believe me, I already tried to run application by locking Read & Write operations with mutex so many times. It didnt work somehow.If you know any code or any test application which has similar scenarios, Could you please point me out? Sorry, I am not very good with QT framework.
Right now, I am trying to understand and implement, kuzulis's points into my application.
@AmitParmar said in Get sigabrt exception when I try to send data using QTcpSocket to InfluxDB:
Right now, I am trying to understand and implement, kuzulis's points into my application.
So you could hav done this already 9 days ago since I already guessed that you're accessing the socket from two different threads, exactly what @kuzulis told you now again.
-
Ohh, I am sorry, I think I miss-understood your comment. I thought you are suggesting me to lock read/write operations so, multiple threads cannot access them at the same time. Anyway, thanks again for the help. Appreciate it.
Also, do you know if there is any similar application or test code which I can look as a reference?
-
Ohh, I am sorry, I think I miss-understood your comment. I thought you are suggesting me to lock read/write operations so, multiple threads cannot access them at the same time. Anyway, thanks again for the help. Appreciate it.
Also, do you know if there is any similar application or test code which I can look as a reference?
@AmitParmar said in Get sigabrt exception when I try to send data using QTcpSocket to InfluxDB:
nt. I thought you are suggesting me to lock read/write operations so,
I also said that you may access the socket from different threads what you're obviously doing - you access a socket from another thread where it lives in.