Get sigabrt exception when I try to send data using QTcpSocket to InfluxDB
-
Hey Friends,
We have multi-threaded realtime QT 4.7 application which runs on Ubuntu 20.04.
I am currently working on enhancements which sends realtime data to InfluxDB over HTTP protocol using QTcpSocket. I have created a new thread which runs inside infinite running main thread and move my QTcpSocket object in to newly created thread using following syntax:
influxdbsocket->moveToThread(influxdbthread);
I am writing data using following syntax:
influxdbsocket->write(dataline);Everything works fine for approximately 10-15 min. I get correct data inserted into database However, App suddenly crashes with sigabrt.
Here's the message i get:
Caught SIGABRT
/lib/x86_64-linux-gnu/libc.so.6(+0x43090) [0x7fac1b348090]
/lib/x86_64-linux-gnu/libc.so.6(gsignal+0xcb) [0x7fac1b34800b]
/lib/x86_64-linux-gnu/libc.so.6(abort+0x12b) [0x7fac1b327859]
/lib/x86_64-linux-gnu/libc.so.6(+0x8d26e) [0x7fac1b39226e]
/lib/x86_64-linux-gnu/libc.so.6(+0x952fc) [0x7fac1b39a2fc]
/lib/x86_64-linux-gnu/libc.so.6(+0x98fac) [0x7fac1b39dfac]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x2d6) [0x7fac1b3a0156]
QByteArray::realloc(int)
QByteArray::resize(int)
/opt/lib/libQtNetwork-test.so.4(+0x5ed63) [0x7fac1b81dd63]
/opt/lib/libQtNetwork-test.so.4(+0xb0753) [0x7fac1b86f753]
/opt/lib/libQtNetwork-test.so.4(+0xb0ad1) [0x7fac1b86fad1]
/opt/lib/libQtNetwork-test.so.4(+0xa41ed) [0x7fac1b8631ed]
test::application::Application::notify(QObject*, QEvent*)
QCoreApplication::notifyInternal(QObject*, QEvent*)
/opt/lib/libQtCore-test.so.4(+0x1b2d0b) [0x7fac1ba87d0b]
/lib/x86_64-linux-gnu/libglib-2.0.so.0(g_main_context_dispatch+0x27d) [0x7fac1b02817d]
/lib/x86_64-linux-gnu/libglib-2.0.so.0(+0x52400) [0x7fac1b028400]
/lib/x86_64-linux-gnu/libglib-2.0.so.0(g_main_context_iteration+0x33) [0x7fac1b0284a3]
QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag)
QEventLoop::processEvents(QFlagsQEventLoop::ProcessEventsFlag)
QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag)
QThread::exec()
/opt/lib/libQtCore-test.so.4(+0xab622) [0x7fac1b980622]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x8609) [0x7fac1b6fe609]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x43) [0x7fac1b424133]I tried to debug the code using 'attach to running application', but It doesnt give me much information. It shows me stack trace of binary files. Can somebody please help me? I have been struggling with this issue past 2 months.
Due to my contract with my company, I cant give any code in public forum.
Thanks In Advance,
Amit@AmitParmar said in Get sigabrt exception when I try to send data using QTcpSocket to InfluxDB:
QByteArray::realloc(int)
QByteArray::resize(int)Maybe your app has a memory leak and is aborted because of out-of-memory?
I would check that. -
Without code we can't say much but I would guess you're accessing data from two different threads without proper locking mechanisms.
Don't know why a QTcpSocket which only writes needs to be in a separate thread at all - it's useless and error-prone (as you can see here).Thanks for quick reply Christian. Answer to your question, We have main thread running infinitely. If main thread blocks more than 20 milli-seconds, the app will throw an exception. so, I use another thread for sending/receiving data incase if sending/receiving operation takes longer than 20 milli-seconds, it doesn't block main thread.
I tried to lock the code using mutex but it didnt help. In test environment, I have only two threads running main thread and inside main thread, write operation is performed.
-
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?
-
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::MasterThread
stuff? If that is callingsocket->readAll()
then, so far as I understand, that must only be called from the thread in whichsocket
lives/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.