Kyle Strand Kyle Strand - 2 months ago 20
Linux Question

QSerialPort cannot open tty after application has previously been run by `root`

I have an application (using

QSerialPort
) that reads and writes from a serial port. When I run this application as the
root
user, then run it again as a non-root user, I am no longer able to write to the serial port, receiving the following error:

QIODevice::write (QSerialPort): device not open


The non-root user is in the
dialout
group, and the permissions on the
/dev/tty**
file in question appear to be unchanged:

crw-rw---T 1 root dialout ......


Weirdest of all, I do not get an error when I simply use my shell to write to the file as the non-root user:

$> echo "foo bar baz" >> /dev/ttyS0
$> echo $?
0


The only thing I've found that appears to fix the problem is rebooting the machine.

What could possibly be going on here?

I'm on Debian 7.

Answer

Update: this is a bug in Qt, and will be fixed in version 5.6.2, which is due for release later this month.

On Linux and Mac, QSerialPort creates a lock file in /var/lock/ when opening a serial port. The lockfile has permissions 0644, i.e. only the creator of the file can write to it.

If the process that opened the serial port dies or if the serial port is somehow improperly closed by any other means, the lock file will not be deleted. The lockfile contains the PID of the process that opened the serial port; if the process is no longer running, Qt will attempt to simply take possession of the lock, changing the PID in the file.

However, since the lockfile has 0644 permissions, if the improperly-closing process was run by root, the new process will be unable to delete or overwrite the lockfile, resulting in a permissions error.

This is fixed for version 5.6.2.

Note that QSerialPort does clean up after itself: when its destructor is called, the port is closed and the lockfile is deleted. However, by default, Qt does not call object destructors when SIGTERM or SIGINT causes the program to exit. (Personally, I think this is also a bug, but I recognize that this is more a matter of opinion.)

Also see the suggested dupe question. As can be seen from this question, the current behavior is actually an improvement--previously, the application would simply hang!

Comments