Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QSerialPort is causing a program stop (endless loop?) if opening device

I want to write on a serial device. Unfortunately I have the feeling the QSerialPort is not properly implemented under linux. In contrast to other methods (python) I get !sometimes! a hang of the program when I try to call:

serial.open(QIODevice::ReadWrite)

I am using the example from http://qt-project.org/wiki/QtSerialPort (see below). The QSerialPortInfo is working properly so that I can search for my device before I open it. The problem appeared in all Qt 5.* series. I am currently using 5.3 beta from the OpenSuse repository. Other tools or methods proof, that the device is working (Windows or Python).

// Example use QSerialPortInfo
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
    qDebug() << "Name        : " << info.portName();
    qDebug() << "Description : " << info.description();
    qDebug() << "Manufacturer: " << info.manufacturer();

    // Example use QSerialPort
    QSerialPort serial;
    serial.setPort(info);
    if (serial.open(QIODevice::ReadWrite)) // Hang of the program
        serial.close();
}

Working python script:

com_port = 4
baud_rate = '9600'
pySerial = serial.Serial(com_port, baud_rate)

Edit: I tested with debugger. Seems to be a problem of Qt 5 at least with linux. It looks like connected with a device lock.

like image 566
dgrat Avatar asked Feb 13 '23 07:02

dgrat


2 Answers

I don't know what Mr. Papp is complaining about; I was able to reproduce your problem without any more information.

On Linux, if the Qt process with an open QSerialPort instance terminates abnormally or the QSerialPort instance is otherwise not destroyed upon process exit, then the lock file hangs around and can cause a problem. A stale lock file shouldn't cause this problem; the lock file contains the crashed application's PID, and the new application instance should recognize that no process with that PID exists and delete the lock immediately before creating a new one. strace will show you the lock file in question repeatedly with increasing backoff time as the new process repeatedly checks to see if the stale lock file has been deleted or whatever. So, delete the file (for example, /var/lock/LCK..ttyS0); you will own the lock file if you ran the application that crashed.

A random side note: if you are using QSerialPort in Python through PyQt5 (which does work, by the way!), be sure you have explicitly deleted the QSerialPort instance before the Python interpreter exits. If you're manipulating the port in IPython, then do "%xdel portobject" before exiting.

It's a dumb workaround, but provided you are using some other mechanism to ensure that you don't have two instances of your program running and using the same port - or if you simply don't care - you could have a line of code delete that lock file before opening the port.

IMHO, Qt shouldn't be emulating completely worthless Windows style nanny state protections in the first place. I can sudo rm -rf / and it happens! I can even rm the serial port. Given such unfettered, primal, god like power, I should be able to open a serial port whenever and however I please...

like image 74
Erik Hvatum Avatar answered Feb 16 '23 02:02

Erik Hvatum


The class tries to obtain lock for serial port. Line lockFileScopedPointer->lock(); in bool QSerialPortPrivate::open(QIODevice::OpenMode mode) Probably the application was run as root and the lock file is inaccessible when the application is run as different user. Run strace to check.

like image 31
grzegorz Avatar answered Feb 16 '23 02:02

grzegorz