QSerialPort вызывает остановку программы (бесконечный цикл?) при открытии устройства

Я хочу писать на последовательном устройстве. К сожалению, у меня такое ощущение, что QSerialPort неправильно реализован в Linux. В отличие от других методов (python) я получаю !иногда! зависание программы при попытке позвонить:

serial.open(QIODevice::ReadWrite)

Я использую пример из http://qt-project.org/wiki/QtSerialPort (см. ниже). QSerialPortInfo работает правильно, поэтому я могу найти свое устройство, прежде чем открыть его. Проблема появилась во всех сериях Qt 5.*. В настоящее время я использую бета-версию 5.3 из репозитория OpenSuse. Другие инструменты или методы, подтверждающие, что устройство работает (Windows или 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();
}

Рабочий скрипт на питоне:

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

Изменить: я тестировал отладчиком. Кажется, это проблема Qt 5, по крайней мере, с Linux. Похоже, связано с блокировкой устройства.


person dgrat    schedule 05.04.2014    source источник
comment
Что вы подразумеваете под QSerialDevice? Нет такого класса! Примеры работают для вас?   -  person lpapp    schedule 06.04.2014
comment
Нет, примеры иногда работают только в моих системах (OpenSuse) с несколькими версиями Qt. PySerial работает всегда (Windows, Linux). На самом деле интересно, это только я или это просто проблема Qt. Впрочем, если с QSerialPort не зависает, то все гладко.   -  person dgrat    schedule 06.04.2014
comment
О каком примере вы говорите? Вы пробовали читать и писать из командной строки? Какую версию Qt вы используете? Возможно, вы используете устаревший QtSerialPort? Откуда вы это взяли? Какой тип последовательного порта вы используете?   -  person lpapp    schedule 06.04.2014
comment
Я использую бета-пакеты 5.30, те же проблемы, что и с 5.2.1.   -  person dgrat    schedule 06.04.2014
comment
Пожалуйста, ответьте на все вопросы. Кроме того, информационный класс распечатывает все правильно, как и ожидалось?   -  person lpapp    schedule 06.04.2014
comment
Информационный класс работает отлично всегда. Я могу определить все устройства.   -  person dgrat    schedule 06.04.2014
comment
Пожалуйста, ответьте на остальные вопросы, которые я задавал. Их важно знать.   -  person lpapp    schedule 06.04.2014
comment
@lpapp Очевидно, что это не так. Ваши уточняющие вопросы больше похожи на разглагольствования.   -  person Kyle Strand    schedule 24.05.2016


Ответы (2)


Я не знаю, на что жалуется мистер Папп; Я смог воспроизвести вашу проблему без дополнительной информации.

В Linux, если процесс Qt с открытым экземпляром QSerialPort аварийно завершается или экземпляр QSerialPort не уничтожается по иным причинам при выходе из процесса, тогда файл блокировки зависает и может вызвать проблему. Устаревший файл блокировки не должен вызывать эту проблему; файл блокировки содержит PID аварийного приложения, и новый экземпляр приложения должен распознать, что процесса с таким PID не существует, и удалить блокировку непосредственно перед созданием новой. strace будет неоднократно показывать вам рассматриваемый файл блокировки с увеличением времени отсрочки, поскольку новый процесс неоднократно проверяет, был ли удален устаревший файл блокировки или что-то еще. Итак, удаляем файл (например, /var/lock/LCK..ttyS0); вы будете владельцем файла блокировки, если вы запустили приложение, которое потерпело крах.

Случайное примечание: если вы используете QSerialPort в Python через PyQt5 (что, кстати, работает!), убедитесь, что вы явно удалили экземпляр QSerialPort перед выходом интерпретатора Python. Если вы манипулируете портом в IPython, перед выходом выполните «%xdel portobject».

Это глупый обходной путь, но при условии, что вы используете какой-то другой механизм, чтобы гарантировать, что у вас нет двух экземпляров вашей программы, работающих и использующих один и тот же порт, или, если вам просто все равно, вы можете удалить строку кода этот файл блокировки перед открытием порта.

ИМХО, Qt не должен в первую очередь эмулировать совершенно бесполезную защиту состояния няни в стиле Windows. Я могу sudo rm -rf / и это происходит! Я даже могу подключить последовательный порт. Учитывая такую ​​неограниченную, первобытную, богоподобную силу, я должен быть в состоянии открыть последовательный порт, когда и как мне заблагорассудится...

person Erik Hvatum    schedule 23.05.2014
comment
Да, если я удалю файл блокировки, то снова смогу получить к нему доступ. К сожалению, я не знаю, почему файл блокировки уже иногда появляется сразу после перезагрузки. - person dgrat; 26.05.2014
comment
Где находятся эти файлы блокировки? - person Goddard; 18.04.2016
comment
Re: Qt не должен эмулировать совершенно бесполезную защиту состояния няни в стиле Windows. Эти средства защиты также усложняют отладку; например, я обнаружил, что запуск моего приложения от имени пользователя root (и неправильный выход) не позволяет повторно запустить его от имени пользователя без полномочий root, но я был озадачен тем, что echo foo >> /dev/<myport> все еще работает. - person Kyle Strand; 24.05.2016
comment
@Goddard Как упоминалось в конце второго абзаца, они находятся в /var/lock, а имя файла указывает на заблокированное устройство. - person Kyle Strand; 24.05.2016
comment
Это расценивается как ошибка, по крайней мере, некоторыми пользователями. В этом потоке признано, что проблема будет решена путем предоставления права доступа 666 файлу блокировки. - person Kyle Strand; 24.05.2016
comment
О, и, наконец, поведение изменилось (в 5.5.1 или более ранних версиях), так что теперь оно выдает ошибку разрешений, а не зависает. - person Kyle Strand; 24.05.2016
comment
Это будет исправлено в версии 5.6.2: bugreports.qt.io/browse/QTBUG-36983. - person Kyle Strand; 16.09.2016

Класс пытается получить блокировку последовательного порта. Строка lockFileScopedPointer->lock(); в bool QSerialPortPrivate::open(QIODevice::OpenMode mode) Вероятно, приложение было запущено от имени пользователя root, и файл блокировки недоступен, когда приложение запускается от имени другого пользователя. Запустите strace для проверки.

person grzegorz    schedule 14.05.2014
comment
Проблема частично в реализации файловой блокировки и возможно проблема моего дистрибутива. К сожалению, не так просто воспроизвести на 100%. - person dgrat; 14.05.2014