Can not close serial port using boost asio - c++

I am having an issue that it seems someone else has encountered but appears to be not asked here. I have a very simple application that right now just opens and closes a serial port using boost asio (just trying to do some simple debugging right now before building a larger application. The calls reside in a qt based gui. The serial communication right now is set up in the window constructor:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(getData()));
timer->start(1000);
std::string comm = "/dev/ttyUSB0";
boost::asio::io_service io;
port = std::shared_ptr<boost::asio::serial_port>(new boost::asio::serial_port(io, comm));
std::cout << "Port has been successfully opened..." << std::endl;
boost::asio::serial_port_base::baud_rate baud(19200);
port->set_option(baud);
std::cout << "Baud rate set to 19200..." << std::endl;
getData();
}
getData will contain calls to the serial port at regular intervals, but right now it just makes a request to populate a time stamp on the gui with the current time.
The port is closed in the destructor
MainWindow::~MainWindow()
{
if (port->is_open()) port->close();
delete ui;
}
When the gui is closed, the destructor is called, but the system just hangs at the port closing. It appears that it is getting stuck in boost's posix_mutex.hpp lock method.
I have seen another post about this (https://cpc110.blogspot.com/2017/03/boost-asio-can-not-close-serial-port.html), but it appears that there is no answer to that one. Does anyone have any thoughts on this?
I am using boost 1.58 and Qt 5.8 on Ubuntu 16.04 LTS.

The problem is probably (I'm pretty new to boost::asio myself) that your io_service is already destructed. Try to make it a member of your MainWindow class.

Related

A simple communicate c/s app using QtUdpSocket

I am a beginner of Qt.I want to use QUdpSocket to write a server app without a GUI.I have writen the client GUI app and server GUI app.They work well.But the server without GUI doesn't work well.
I try to use a while(true) loop to make the app running ,because I think after the code 'return a.exec()' the app will stop.But my server app does't work.
Here is my code:
client with GUI:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
socket=new QUdpSocket(this);
//click pushbutton send message to server
connect(this->ui->pushButton,SIGNAL(clicked()),this,SLOT(send()));
}
Widget::~Widget()
{
delete ui;
}
//send message
void Widget::send()
{
QByteArray msg="client2:hello world";
socket->writeDatagram(msg.data(),msg.size(),QHostAddress::LocalHost,6666);
}
The client app and server with GUI app can work well.But When I try to make a server app without GUI,I found server can not get the message from client.
And here is my server.cpp without GUI:
#include "server.h"
Server::Server(QObject *parent) : QObject(parent)
{
socket=new QUdpSocket(this);
array=new QByteArray();
socket->bind(QHostAddress::LocalHost,6666,QAbstractSocket::DontShareAddress);
socket->open(QIODevice::ReadWrite); //without this line, the app will show:
//'QIOBevice::read(QUdpSocket):device not open',but it still can get the message from client.
connect(socket,SIGNAL(readyRead()),this,SLOT(printMsg()));
}
void Server::printMsg()
{
if(socket->hasPendingDatagrams()) //I forgot this line before.
{
array->resize(socket->pendingDatagramSize());
socket->readDatagram(array->data(),array->size());
socket->readAll();
qDebug()<<"yesyesyes";
}
}
I try many times,I think the problem is in my main.cpp:
#include <QCoreApplication>
#include "server.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Server s;
return a.exec();//after a.exec(),the app is still working!!!
}
In a GUI app, if I don't close the windows, the server app will always run, and the SIGNAL and SLOT I can understand.But in a console app, it seems that the app end fast and can't get the message from client(can't display the message).
You should not have a while(true) in your main, otherwise, you are effectively just freezing your thread and Qt application. This is exactly what app.exec(); is for, it will return when your application is closed (more details here)
If your application (with or without GUI) closes after calling app.exec(), it is due to one of the following:
You are closing it manually, e.g. with qApp->quit();
You are forcing an exit, e.g. with exit(1);
A fatal error or exception prematurely ends your application

QNetworkAccessManager used by QTimer causes falling

I am using QNetworkAccessManager in function, which is run periodically by QTimer. The code is:
QTimer* timer=new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(findUpdate()));
timer->setSingleShot(false);
timer->start(frequency*1800000);
void MainWindow::findUpdate()
{
for (int i=0;i<aplikace.count();i++){
QNetworkAccessManager* manager=new QNetworkAccessManager(this);
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(checkUpdate(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://www.gibucsoft.8u.cz/"+lang+"gibuclauncher/verze.php?ver="+aplikace.at(i))));
}
}
The compilation is fine and when I run my application from the Qt Creator it is OK as well but when I run it from the OS the program falls after a while (but not long enough for the timer to even start the function findUpdate). Sometimes before falling this error message shows:
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.

QT Creator : Program crashes in debug mode but working in Release mode and in DEBUG Mode with breakpoints for QThread based program

I am working on a Desktop (Windows 7) based application and using Qt Creator v 5.6.0 for development of the Program.
I have a very strange issue i.e.
My Program crashes in DEBUG mode but works fine in RELEASE mode.
If in DEBUG mode, and I put break points to find the reason of the crash, then it doesn't crash: It work properly. But if I do not put any break points then it crashes at below code:
Project Background:
My Project includes functionality to read from the device connected at System communication port and transmits data to the MainWindow UI to display. Since to communicate with the communication port we have to use the third party library so I am not using QtSerial Port class which is much simpler and easy to use.
Code Design:
Class MainClass : In this class we have created some forms to display the data read from the device.
Class TestClass: This class will handle all the communication with the device connected at the system Serial Port and use the third party library. This class also have the while loop to read data from the device connected at Serial Port.
Since Test Class is using while loop. So we decided to make a Test Class run in different Thread.
Code for creating Thread in MainClass Constructor:
MainClass::MainClass (QWidget *parent) : QDialog(parent),
ui(new Ui::Analzyer)
{
............................
............................
workerThread = new QThread;
testClassObject = new TestClass(); // Declared in HeaderFile of MainClass
if((workerThread != NULL) && (testClassObject != NULL))
{
workerThread ->moveToThread(testClassObject );
connect(workerThread , SIGNAL(started()), testClassObject, SLOT(SomeFunc()));
connect(testClassObject, SIGNAL(exit()), workerThread , SLOT(quit()));
connect(testClassObject, SIGNAL(exit()), testClassObject, SLOT(deleteLater()));
connect(workerThread , SIGNAL(finished()), workerThread , SLOT(deleteLater()));
// connectToPort Signal is emitted when User clicks the pushbutton from // Main class UI
connect(this, SIGNAL(connectToPort(QString)), testClassObject, SLOT(openPort(QString)));
}
}
Crash Code:
void TestClass::openPort(const QString portName)
{
// Here portName is say : "Appliance Interface v2"
quint32 param2 = getParam2ForPortName(portName);
qint16 portNumber = 0;
QByteArray portNameByteArray = portName.toLatin1();
const char *portNameToOpen = portNameByteArray.data();
// Program crashed when return from this function
if(func1(portNameToOpen , param2, 10 , &portNumber) == true)
{
......................
......................
}
}
Here, I added some qDebug() and found that my code crashes when it returns from or call the func1() which is getting called in slot OpenPort(). Below is the prototype of the func1()
bool func1 (const char portDescription[], uInt32 param2,
uInt16 length, Int16 * portNr);
Since, func1() is the part of the library code. So I can not check the defination of the function func1(). I can assure that there is no problem in func1() Since it is being used in different java based projects and it works.
I did some more debugging on the Project and noticed that when in Run in DEBUG Mode with BreakPoints than in the QT Thread Debug Window I can see my connected Slot but when I do not put any breakPoint than my code crashes and in Qt Thread Debug Window I can not see my connected Slot
So, It looks the problem of connection between the Main Class and the Test Class for openPort Slot.
But I am not able to understand taht when i put breakpoints in operPort() function than I can see my openPort Slot in Qt Thread Debug window but when no breakpoints than openPort Slot is not visible in Qt Thread Debug Window and Program Crashes.
Kindly Suggest,
I can assure that there is no problem in func1() Since it is being used in different java based projects and it works.
Wait, is func1() C++ or Java ?
Also, how can you be sure it works ?
Get the library source, compile it yourself, and debug in it.
And, just to be sure, check values of your variables while debugging, and qDebug() them when not debugging
I apologise for replying on my own post but after lots of dicussion on StackOverflow and google. I was able to solve the Issue.
To Solve the Issue:
I changed the SLOT(openPort) as mentioned below:
Connect(this, SIGNAL(connectToPort(QString)), testClassObject, SLOT(openPort(QString)), Qt::DirectConnection);
That is to use the "Qt:DirectConnection" method. If we don't specify a connection method, the direct method is automatically used for connections between objects on the SAME thread.
Since here we have created a new QThread for TestClass and using a thirdParty library which might not be a thread safe.
So using "Qt::DirectConnection" make the openPort() SlOT to run in MainClass Thread. Basically, it's as if emitting the signal calls the slot method "directly".

Qt incomingConnections not called

I have compiled Qt's Trip Planner example that uses QTcpSocket and QTcpServer to create a client and server.
The problem is, the server's incomingConnection() slot is not being called. Even though the client connects to the server successfully. Therefore, the socket's readyRead() signal is never emitted and the client gets no data back.
tripserver.cpp
TripServer::TripServer(QObject *parent)
: QTcpServer(parent)
{
}
void TripServer::incomingConnection(int socketId)
{
qDebug() << "Incoming Connection";
ClientSocket *socket = new ClientSocket(this);
socket->setSocketDescriptor(socketId);
}
If I add a newConnection() slot, it gets called. So what is going on?
Found my answer.
The parameter list has changed since Qt 4.8.1
http://qt-project.org/doc/qt-5.0/qtnetwork/qtcpserver.html#incomingConnection
void TripServer::incomingConnection(qintptr socketId){}

QT GUI freezes even though Im running in separate thread

I have a small chat application where I use a SQLite database to store all the conversations. I've noticed that the app freezes randomly, and I then have to minimize and maximize it to make it work again. I thought that the problem might be the SQLite selects / inserts that were causing the gui to freeze. I decided to try and move all the SQLite methods into a separate thread.
After doing so the app still freezes.
Some things that might be worth knowing:
I use QTcpSocket directly in my MainWindow but it seems that there is no use in running the QTcpSocket in a separate thread?
I have separated the SQLite methods into a new thread (see implementation below)
I use 3 WebViews for displaying my chat messages, the entire application GUI is build with these WebViews
Does my code below really run in a separate thread? GUI still freezes.
My header file:
class dbThread : public QObject
{
Q_OBJECT
public:
dbThread(QObject* parent);
public slots:
bool openDB(QString agentID);
signals:
void clearPreviousHistory();
private:
QSqlDatabase db;
QHash<QString, QString> countries;
};
My cpp file:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QThread* thread = new QThread(this);
dbtrad = new dbThread(this);
dbtrad->moveToThread(thread);
dbtrad->openDB(userID);
connect(dbtrad, SIGNAL(clearPreviousHistory()), this, SLOT(clearHistoryV()));
thread->start();
}
dbThread::dbThread(QObject * parent): QObject(parent) {
}
bool dbThread::openDB(QString agentID) {
qDebug() << "OPEN DB FROM THREAD ";
// Find QSLite driver
db = QSqlDatabase::addDatabase("QSQLITE");
// ......
}
This is how I call dbThread methods from my MainWindow:
dbtrad->getHistory(channelId);
Edit
New code:
// Start database thread
QThread* thread = new QThread(this);
dbtrad = new dbThread(this);
dbtrad->moveToThread(thread);
connect(this, SIGNAL(requestOpenDB(QString)), dbtrad, SLOT(openDB(QString)));
thread->start();
emit requestOpenDB(userID);
dbtrad->openDB(userID); will execute like any normal function (Why should it?), in the GUI thread.
moveToThread allow you to execute slots called using signals in a separate thread.
If you want to execute openDB in the thread you can trigger its execution using
connect (thread, SIGNAL(started()), dbtrad, SLOT(openDBWithUIDAlreadySet()))
or
connect (this, SIGNAL(requestOpenDB(int)), dbtrad, SLOT(openDB(int)))
You need to use existing or additional signals. Qthread::start() emit the signal started(). You can also define
MainWindow{
signals:
void requestOpenDB(int);
void queryHistory(int channelid);
}
and emit the signals manually using
emit requestOpenDB(userID); //for openDB
emit queryHistory(channelId); // for getHistory
the responses from the dbThread object also need to be given using a signal which is connected to a slot. Like a notification.
QTcpSocketdoes indeed not need to be in a separated thread.
as long as all the database access is done from that thread where the database was created it should also be no problem
And now to the fun part: i think you create the database in the main thread ... by calling dbtrad->openDB(userId)
Yes so qt moveToThread() does not do what you are expecting it to do. The function that you are calling from your main thread will get executed in your main thread only. That database access is causing GUI freezes.
moveToThread only moves "event processing" in a seperate thread. Which means any slots of dbThread which are connected using Qt::QueuedConnectionwill get executed in new thread.
Following way will execute getHistory() method in your main ui thread only. You need to create a signal in main thread and make getHistory() a slot of dbThread class. Then connect both.
Reading documentation AND logs is essential!!!
In log you have a warning that YOU CAN"T MOVE TO THREAD IF OBJECT HAVE A PARENT.
Also documentation clearly says that:
Changes the thread affinity for this object and its children. The
object cannot be moved if it has a parent. Event processing will
continue in the targetThread.
Proper way to fix it:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
thread = new QThread(this);
dbtrad = new dbThread(); // NO PARENT
dbtrad->moveToThread(thread);
// run object method in thread assigned to this object:
QMetaObject::invokeMethod(dbtrad, "openDB", Qt::QueuedConnection, Q_ARG(QString, userID));
connect(dbtrad, SIGNAL(clearPreviousHistory()), this, SLOT(clearHistoryV()));
thread->start();
}
MainWindow::~MainWindow()
{
dbtrad->deleteLater();
thread->quit();
thread->wait(5000); // wait max 5 seconds to terminate thread
}