How to solve the QSerialPort::ResourceError on Linux platform?
-
@SGaist said in How to solve the QSerialPort::ResourceError on Linux platform?:
You remove your device while it's in use.
SerialCommunicator::SerialCommunicator(const InstrumentInfo &info, QObject *parent) : QObject(parent) { _rawData.reserve(1024*1024); _serialThread = new SerialThread(info); connect(_serialThread, &SerialThread::NewData, this, &SerialCommunicator::DataArrived, Qt::QueuedConnection); connect(this, &SerialCommunicator::SendData, _serialThread, &SerialThread::DataToSend, Qt::QueuedConnection); } SerialCommunicator::~SerialCommunicator() { if (_serialThread->isRunning()) { _serialThread->quit(); _serialThread->wait(); } _serialThread->deleteLater(); }I am receiving some initial information from device with help of sub thread. I create objects
SerialCommunicator communicator(info)on subthread. and object will delete because ofcommunicatorgoes out of scope.Now, if I will get initial information properly then I am creating object of
SerialCommunicatoron main thread and object will alive until device is connected.I was thinking it resource error due to threading. So that I modified all code, Now I am creating only one object of
SerialCommunicator(for single port) through out application. It will all received information.But still I am at same page nothing is change. I am getting same error.
few things I would like to mention. It may help.
After this error:QSerialPort::ResourceError_serialPort->isReadable()and _serialPort->isWritable() are return true.- if I am trying write data on USB port then I am successfully send it.
od -xc < /dev/ttyACM0give bash: /dev/ttyACM0: Device or resource busy
In addition, If I will put the break point or take some time by writing some dummy statement, then I am able to successful make communication in case 1.
-
@Yash001 do you really need to use threads? Inproper synchronisation can lead to unexplainable behavior. QSerialPort buffrs data in background, so there's rarely a need for threads.
Regards
@aha_1980 said in How to solve the QSerialPort::ResourceError on Linux platform?:
do you really need to use threads? Inproper synchronisation can lead to unexplainable behavior.
I was thinking same things. So that, I modify the code, and now I am creating only one object of
SerialCommunicatorfor single port in throughout application, and I am creating object from main thread.If you are talking about this thread
SerialThread::run()then yes I need this thread because of I am keeping port open until device is connected to USB port. And just want to information I am callingSerialThread::start()function only single time in application. -
@aha_1980 said in How to solve the QSerialPort::ResourceError on Linux platform?:
do you really need to use threads? Inproper synchronisation can lead to unexplainable behavior.
I was thinking same things. So that, I modify the code, and now I am creating only one object of
SerialCommunicatorfor single port in throughout application, and I am creating object from main thread.If you are talking about this thread
SerialThread::run()then yes I need this thread because of I am keeping port open until device is connected to USB port. And just want to information I am callingSerialThread::start()function only single time in application.@Yash001 said in How to solve the QSerialPort::ResourceError on Linux platform?:
then yes I need this thread because of I am keeping port open until device is connected to USB port
And why do you think you need a thread for that?
-
@Yash001 said in How to solve the QSerialPort::ResourceError on Linux platform?:
then yes I need this thread because of I am keeping port open until device is connected to USB port
And why do you think you need a thread for that?
@jsulm said in How to solve the QSerialPort::ResourceError on Linux platform?:
why do you think you need a thread for that?
So that I can collect the data on different thread. and manipulate data on different thread so that I want that functionalities to be very fast.
In addition,
Today I modify the SerialThread. and remove thread QThread. Here my new SeraulThread.class SerialThread : public QObject { Q_OBJECT public: SerialThread(const InstrumentInfo&); InstrumentInfo getInstrumentInfo() { return _info; }; void waitForBytesWritten() { _serialPort->waitForBytesWritten(1000); }; //protected: void run(); void quit(); signals: void NewData(const QByteArray&); public slots: void DataToSend(const QByteArray&); private slots: void DataArrived(); void ErrorOnSerial(QSerialPort::SerialPortError); private: QSerialPort *_serialPort; InstrumentInfo _info; };SerialThread::SerialThread(const InstrumentInfo &info) : _info(info) { //this->moveToThread(this); LOG() <<"serail thread is created"; } // Detect the new instruments and read the data from instruments void SerialThread::run() { _serialPort = new QSerialPort(this); _serialPort->setPortName(_info.port.name); _serialPort->setBaudRate(DefaultSerialPortSettings::Baudrate()); _serialPort->setDataBits(DefaultSerialPortSettings::DataBits()); _serialPort->setFlowControl(DefaultSerialPortSettings::FlowControl()); _serialPort->setParity(DefaultSerialPortSettings::Parity()); _serialPort->setStopBits(DefaultSerialPortSettings::StopBits()); connect(_serialPort, &QSerialPort::readyRead, this, &SerialThread::DataArrived, Qt::QueuedConnection); connect(_serialPort, &QSerialPort::errorOccurred,[=](QSerialPort::SerialPortError error){ LOG() <<"error on serial port" << error; }); //connect(_serialPort, &QSerialPort::errorOccurred, this, &SerialThread::ErrorOnSerial); _serialPort->open(QIODevice::ReadWrite); //exec(); } void SerialThread::quit(){ _serialPort->close(); _serialPort->deleteLater(); } // executation is quit if data has error. void SerialThread::ErrorOnSerial(QSerialPort::SerialPortError error) { if (QSerialPort::NoError == error) { return; } //this->quit(); } // data send to COM port void SerialThread::DataToSend(const QByteArray &data) { if (!_serialPort->isWritable()) { return; } _serialPort->write(data); } // if data is safly arived then read from port void SerialThread::DataArrived() { emit NewData(_serialPort->readAll()); }I am still getting resource error.
-
Can you explain the exact logic of your application with regards to selecting the USB port and starting the thread ?
-
Can you explain the exact logic of your application with regards to selecting the USB port and starting the thread ?
I have
InstrumentEnumeratorclass. which is inherits from QThread.
InstrumentEnumerator::run()function haswhile(1) loop. while loop containQSerialPortInfo::availablePorts();.If new port is found, and if it is our device then
addInstrumentsignal is emit fromInstrumentEnumerator::run(), with argument asportname.SIGNALE
InstrumentEnumerator::addInstrumentconnected withMainWindow::addInstrumentsolt.MainWindow::addInstrumentslot create the object ofInstrumentOpratorclass.object of
InstrumentOpratortake port name as arguments, create the object ofSerialCommunicator.object of
SerialCommunicatortake port name as arguments, create the object ofSerialThread.SerialThread:: run()method is create the object ofQSerialPortand keep open port.
(just for testing purpose I changed, earlier it was as run on separate thread.)SerialThread::run()method is called fromSerialCommunicator::start()method;SerialCommunicator::start()method is called from constructor ofInstrumentOprator. So In general, constructor of InstrumentOprator do two things 1) create the object ofSerialCommunicatorand 2) callSerialCommunicator::start().Few other detail:
- I am calling InstrumentEnumerator::start() from constructor of MainWindow class.
- class Serialthread communicate with only QserialPort.
- class SerialCommunicator make frame and decode frame, send and received data from Serialthread.
- class InstrumentOprator is Communicate with MainWindow and SerialCommunicator.
-
Hi,
may I suggest two approaches towards narrowing the area of search for a problem (I am sorry if you've been there but I am not able to tell what you already know, just what you've written here):- are you completely sure that we can eliminate external issue? Lack of privileges for the user that program runs can cause odd things, depending on the distro;
- for the sake of dealing with @SGaist suspicions, are you able to modify the program/create a boileplate code that will do the same operations on the port but without deferring to the threads?
Kind Regards,
Artur -
Hi,
may I suggest two approaches towards narrowing the area of search for a problem (I am sorry if you've been there but I am not able to tell what you already know, just what you've written here):- are you completely sure that we can eliminate external issue? Lack of privileges for the user that program runs can cause odd things, depending on the distro;
- for the sake of dealing with @SGaist suspicions, are you able to modify the program/create a boileplate code that will do the same operations on the port but without deferring to the threads?
Kind Regards,
Artur@artwaw said in How to solve the QSerialPort::ResourceError on Linux platform?:
are you completely sure that we can eliminate external issue? Lack of privileges for the user that program runs can cause odd things, depending on the distro;
I install new Ubuntu 18.04 and Qt 5.13.1. After that I add my self to dialout group
sudo usermod -a -G dialout $USER. I hope this is enough for making communication with USB Port. did I missing anything?@artwaw said in How to solve the QSerialPort::ResourceError on Linux platform?:
for the sake of dealing with @SGaist suspicions, are you able to modify the program/create a boileplate code that will do the same operations on the port but without deferring to the threads?
I remove completely thread and eventloop from serial thread class, but still i am getting that issue.
In addition, sometime I am able to generate same error in
example/serialport/terminalwith baud rate 57600. I am not able to find out certain pattern to regenerate that error.My device is continuously sending data frame as soon as I connect to usb port. Terminal example is printing that data on console.
I follow this steps with terminal example:
- open serial port
- remove usb cable from port.
- again connect usb cable to usb port.
- open port (here some data will print and after that sometime I am getting error resource or some time I am not getting.)
-
Are you letting the system some oxygen ?
Spamming as fast as possible to find if a new device was added doesn't sound like a good design.I would rather use something like KDE's Solid framework to get a notification when something changed on the USB side.