How to solve the QSerialPort::ResourceError on Linux platform?
-
Hi,
OS: Ubuntu 18.04
Qt: Qt 5.13.1
I am using QSerialport for communicating with hardware. I am getting error likeQSerialPort::ResourceError
while reading data from usbport.I checked my device is connect to usb port (according to lsusb).
I am able to regenerate this error with help of certain step only.
Error will generate:
case 1: If User will open application first, and after that user will connect device through USB port.
-- for few seconds it make communication to device through USB port, After that that I am getting errorQSerialPort::ResourceError
Error will not generated:
case 2: If User will connect device first through USB port, and after that User will open application.In both case if it is windows or Mac then it is work perfectly. I am getting this error only on Linux platform.
Here My SerialThread which is interact with Port.
SerialThread::SerialThread(const InstrumentInfo &info) : _info(info) { LOG()<<"serial thread is created "; this->moveToThread(this); } SerialThread::~SerialThread(){ LOG() <<"serail thread is delete"; } // Detect the new instruments and read the data from instruments void SerialThread::run() { LOG() <<"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 is generaedted " << error; }); //connect(_serialPort, &QSerialPort::errorOccurred, this, &SerialThread::ErrorOnSerial); _serialPort->open(QIODevice::ReadWrite); exec(); LOG()<<"port will be close"; _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; } LOG()<<"writing "; _serialPort->write(data); } // if data is safly arived then read from port void SerialThread::DataArrived() { LOG()<<"reading "; emit NewData(_serialPort->readAll()); }
Here Log out put:
0/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | serial thread is created 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | run 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | error is generaedted QSerialPort::NoError 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | port open sstatus : true 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | writing 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | port will be close 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | serial thread is created 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | run 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | error is generaedted QSerialPort::NoError 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | port open sstatus : true 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | writing 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | writing 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | writing 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | writing 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | writing 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | writing 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | port will be close 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | serial thread is created 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | run 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | error is generaedted QSerialPort::NoError 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | port open sstatus : true 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | writing 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | writing 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | reading 10/21/19 4:06 PM | ../../SquidStat/SquidStat/SerialThread.cpp | error is generaedted QSerialPort::ResourceError
-
Hi,
Did you check your system logs ?
If so, was there anything related to the usb serial port ? -
Hi @SGaist,
@SGaist said in How to solve the QSerialPort::ResourceError on Linux platform?:
If so, was there anything related to the usb serial port ?
Yes, I check syslog file using
tail -f /var/log/syslog
. But I did not find any different in between working case (case 2) and not working case (case 1 ).@Yash001 said in How to solve the QSerialPort::ResourceError on Linux platform?:
Error will generate:
case 1: If User will open application first, and after that user will connect device through USB port.
-- for few seconds it make communication to device through USB port, After that that I am getting error QSerialPort::ResourceError
Error will not generated:
case 2: If User will connect device first through USB port, and after that User will open application.Here the log file for case 1 (give error in Qt):
**start Application**: Oct 24 11:43:31 ****************** org.gnome.Shell.desktop[1373]: Window manager warning: Invalid WM_TRANSIENT_FOR window 0x2600008 specified for 0x2600006 (SquidStat). **PlugIn USB Cable:** Oct 24 11:44:22 ****************** kernel: [86825.548844] usb 3-1: new full-speed USB device number 7 using ohci-pci Oct 24 11:44:22 ****************** kernel: [86825.769712] usb 3-1: not running at top speed; connect to a high speed hub Oct 24 11:44:22 ****************** kernel: [86825.785469] usb 3-1: New USB device found, idVendor=04d8, idProduct=000a, bcdDevice= 1.00 Oct 24 11:44:22 ****************** kernel: [86825.785473] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 Oct 24 11:44:22 ****************** kernel: [86825.785475] usb 3-1: Product: Squidstat Oct 24 11:44:22 ****************** kernel: [86825.785477] usb 3-1: Manufacturer: Company Name Oct 24 11:44:22 ****************** kernel: [86825.788202] cdc_acm 3-1:1.0: ttyACM0: USB ACM device Oct 24 11:44:22 ****************** mtp-probe: checking bus 3, device 7: "/sys/devices/pci0000:00/0000:00:04.0/usb3/3-1" Oct 24 11:44:22 ****************** mtp-probe: bus: 3, device: 7 was not an MTP device Oct 24 11:44:22 ****************** snapd[769]: hotplug.go:199: hotplug device add event ignored, enable experimental.hotplug Oct 24 11:44:22 ****************** upowerd[959]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1/3-1:1.0 Oct 24 11:44:22 ****************** upowerd[959]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1/3-1:1.1 Oct 24 11:44:22 ****************** upowerd[959]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1 Oct 24 11:44:36 ****************** ModemManager[767]: <info> [device /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1] creating modem with plugin 'Generic' and '1' ports Oct 24 11:44:36 ****************** ModemManager[767]: <warn> Could not grab port (tty/ttyACM0): 'Cannot add port 'tty/ttyACM0', unhandled serial type' Oct 24 11:44:36 ****************** ModemManager[767]: <warn> Couldn't create modem for device '/sys/devices/pci0000:00/0000:00:04.0/usb3/3-1': Failed to find primary AT port **Unplug USB cable** Oct 24 11:46:18 ****************** kernel: [86941.232476] usb 3-1: USB disconnect, device number 7 Oct 24 11:46:18 ****************** kernel: [86941.233272] cdc_acm 3-1:1.0: failed to set dtr/rts Oct 24 11:46:18 ****************** upowerd[959]: unhandled action 'unbind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1/3-1:1.1 Oct 24 11:46:18 ****************** upowerd[959]: unhandled action 'unbind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1/3-1:1.0 Oct 24 11:46:18 ****************** upowerd[959]: unhandled action 'unbind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1
case 2 Log file (Error is not generated:)
**Application start:** Oct 24 11:50:59 ****************** kernel: [87222.624713] usb 3-1: new full-speed USB device number 8 using ohci-pci Oct 24 11:50:59 ****************** kernel: [87222.846069] usb 3-1: not running at top speed; connect to a high speed hub Oct 24 11:50:59 ****************** kernel: [87222.866765] usb 3-1: New USB device found, idVendor=04d8, idProduct=000a, bcdDevice= 1.00 Oct 24 11:50:59 ****************** kernel: [87222.866774] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 Oct 24 11:50:59 ****************** kernel: [87222.866779] usb 3-1: Product: Squidstat Oct 24 11:50:59 ****************** kernel: [87222.866783] usb 3-1: Manufacturer: Company Name Oct 24 11:50:59 ****************** kernel: [87222.869289] cdc_acm 3-1:1.0: ttyACM0: USB ACM device Oct 24 11:50:59 ****************** mtp-probe: checking bus 3, device 8: "/sys/devices/pci0000:00/0000:00:04.0/usb3/3-1" Oct 24 11:50:59 ****************** mtp-probe: bus: 3, device: 8 was not an MTP device Oct 24 11:50:59 ****************** snapd[769]: hotplug.go:199: hotplug device add event ignored, enable experimental.hotplug Oct 24 11:50:59 ****************** upowerd[959]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1/3-1:1.1 Oct 24 11:50:59 ****************** upowerd[959]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1/3-1:1.0 Oct 24 11:50:59 ****************** upowerd[959]: unhandled action 'bind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1 Oct 24 11:51:04 ****************** org.gnome.Shell.desktop[1373]: Window manager warning: Invalid WM_TRANSIENT_FOR window 0x2600008 specified for 0x2600006 (SquidStat). Oct 24 11:51:06 ****************** gnome-shell[1373]: value "-1.000000" of type 'gfloat' is invalid or out of range for property 'width' of type 'gfloat' Oct 24 11:51:06 ****************** gnome-shell[1373]: value "-1.000000" of type 'gfloat' is invalid or out of range for property 'height' of type 'gfloat' Oct 24 11:51:06 ****************** gnome-shell[1373]: value "-1.000000" of type 'gfloat' is invalid or out of range for property 'width' of type 'gfloat' Oct 24 11:51:06 ****************** gnome-shell[1373]: value "-1.000000" of type 'gfloat' is invalid or out of range for property 'height' of type 'gfloat' Oct 24 11:51:13 ****************** ModemManager[767]: <info> [device /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1] creating modem with plugin 'Generic' and '1' ports Oct 24 11:51:13 ****************** ModemManager[767]: <warn> Could not grab port (tty/ttyACM0): 'Cannot add port 'tty/ttyACM0', unhandled serial type' Oct 24 11:51:13 ****************** ModemManager[767]: <warn> Couldn't create modem for device '/sys/devices/pci0000:00/0000:00:04.0/usb3/3-1': Failed to find primary AT port **USBPort Disconnected:** Oct 24 11:52:55 ****************** kernel: [87338.847560] usb 3-1: USB disconnect, device number 8 Oct 24 11:52:55 ****************** kernel: [87338.848385] cdc_acm 3-1:1.0: failed to set dtr/rts Oct 24 11:52:55 ****************** systemd[1]: Starting Cleanup of Temporary Directories... Oct 24 11:52:55 ****************** upowerd[959]: unhandled action 'unbind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1/3-1:1.1 Oct 24 11:52:55 ****************** upowerd[959]: unhandled action 'unbind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1/3-1:1.0 Oct 24 11:52:55 ****************** upowerd[959]: unhandled action 'unbind' on /sys/devices/pci0000:00/0000:00:04.0/usb3/3-1 Oct 24 11:52:55 ****************** systemd[1]: Started Cleanup of Temporary Directories.
-
Are you sure your USB device is working properly ?
-
@SGaist
Yes It is working properly in Mac and Windows with same code.One things I came to know if I will remove device from USB port then auto
auto availablePorts = QSerialPortInfo::availablePorts();
is recognized device is removed.Here the log for last two line:
10/24/19 1:38 PM | ../../SquidStat/SquidStat/SerialThread.cpp | error on serial port: QSerialPort::ResourceError 10/24/19 1:38 PM | ../../SquidStat/SquidStat/InstrumentEnumerator.cpp | Plus1102 is disconnected
-
Re-reading your issue, I am not sure what you are after. That is a normal behaviour. You remove your device while it's in use. Why would you except your application to stay silent about that ?
-
@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 ofcommunicator
goes out of scope.Now, if I will get initial information properly then I am creating object of
SerialCommunicator
on 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/ttyACM0
give 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.
-
@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
SerialCommunicator
for 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?
-
@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 ?
-
I have
InstrumentEnumerator
class. 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
addInstrument
signal is emit fromInstrumentEnumerator::run()
, with argument asportname
.SIGNALE
InstrumentEnumerator::addInstrument
connected withMainWindow::addInstrument
solt.MainWindow::addInstrument
slot create the object ofInstrumentOprator
class.object of
InstrumentOprator
take port name as arguments, create the object ofSerialCommunicator
.object of
SerialCommunicator
take port name as arguments, create the object ofSerialThread
.SerialThread:: run()
method is create the object ofQSerialPort
and 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 ofSerialCommunicator
and 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 -
@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/terminal
with 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.