Russian Qt Forum
Май 15, 2024, 22:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
   Начало   Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
Страниц: 1 2 [3] 4 5 ... 10
 21 
 : Апрель 07, 2024, 07:43 
Автор denantikvar - Последний ответ от denantikvar
Куплю для себя в коллекцию или можно обменять старые Швейцарские франки CHF ( в том числе 8 серия ! ), старые бумажные английские фунты стерлингов вышедшие из оборота и уже не являющиеся платёжным средством +79997153560 звоните или пишите вацап, интересует любые номиналы.

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

Покупаю купюры которые не принимают в банки и уже нельзя сдать обменять в обменные пункты. 

Возможен выезд к Вам оценка, покупка и обмен.Если Вы хотите продать или поменять, то пишите Ваши предложения на WhatsApp и Viber +79997153560





 22 
 : Апрель 06, 2024, 13:37 
Автор sergek - Последний ответ от Igor_S
Как же я смогу это сделать, если ~QModbusRtuClient уже исполнился, а краш происходит через несколько секунд?
напр так
Код:
QModbusRtuClient::~QModbusRtuClient( void )
{
 printf("~QModbusRtuClient %p\n", this);
}
И при краше сравнить receiver c напечатанным.
Но поздно - я уже все переделываю, не хочется возвращаться к проблеме, которая имеет чисто академический интерес))
Хорошо если так  Улыбающийся

 23 
 : Апрель 05, 2024, 19:54 
Автор sergek - Последний ответ от sergek
Как же я смогу это сделать, если ~QModbusRtuClient уже исполнился, а краш происходит через несколько секунд? Проблема-то в том и состоит, что процессы, приводящие к аварийному завершению, связаны (ну, я так думаю;)) с сокетом, а приемник уже уничтожен.
Прямо вот сейчас пришла мысль - можно было бы создать отладочный объект-приемник, который живет все время работы программы, и подключить его к возможным источникам сигналов. Но поздно - я уже все переделываю, не хочется возвращаться к проблеме, которая имеет чисто академический интерес))

 24 
 : Апрель 05, 2024, 16:21 
Автор SektorCT - Последний ответ от SektorCT
Нашел вариант, пробижаться по тексту и найти индекс начала и конца слова, и через метод select() с 2 аргументами выделить слово.
Но вот есдинственное что не могу найти, так это как отобразить ту область в тексте где найдено слово.
Как понимаю надо наверное перейти к курсору.
Может кто подсказать, вдруг имели опыт.

 25 
 : Апрель 05, 2024, 10:55 
Автор sergek - Последний ответ от Igor_S
Маловато "фактов". Хорошо бы получить останов (или хотя бы краш) в своем коде/фильтре. Посмотреть что за QEvent, здесь вариантов немного. Убедиться что это действительно удаление, печатая в ~QModbusRtuClient адрес экземпляра

 26 
 : Апрель 04, 2024, 17:00 
Автор sergek - Последний ответ от sergek
Здесь на лицо проблема конкурентного доступа к экземпляру объекта. Обработка сообщений происходит в одном потоке, удаление объекта в другом.
Можно проверить это с помощью определения своего типа производного QModbusRtuClient, например, и вывода и сравнении информации о потоке в деструкторе и обработчиках сигналов.
Только не это. Обработка сообщений и удаление объектов осуществляется в одном потоке - в потоке ядра. Собственно, ядро владеет конфигурацией, его задача - обеспечение асинхронного взаимодействия с периферийным железом.
Запуск обновления конфигурации осуществляется из другого, клиентского потока, в котором живет веб-интерфейс. взаимодействие клиентских потоков с ядром - через сигнал/слотовый механизм. Я использую для этого специальный класс (потоковый адаптер).

По остальным замечаниям - позже, когда освобожусь немного.

 27 
 : Апрель 04, 2024, 15:23 
Автор sergek - Последний ответ от ssoft
Крах программы наблюдается, когда я перед загрузкой новой конфигурации удаляю старые объекты контроллеров, использующих протоколы modbus rtu по протоколу TCP/IP. Это мой компонент (QModbusRtuClient), я сделал его на основе уже имеющихся в составе qtserialbus, исходники я публиковал где-то здесь. Ключевые фрагменты кода (не существенные части я пропускаю, отмечено '...'):

Код
C++ (Qt)
CModbusInterface::CModbusInterface(...) {
...
       //
       modbusDevice = new QModbusRtuClient(this);
...
}
 
CModbusInterface::~CModbusInterface(){
   if (modbusDevice) {
       modbusDevice->deleteLater();
   }
}
 

Фрагмент кода не должен приводить к краху по рассматриваемой причине.
Код в деструкторе лишний, так как при конструировании modbusDevice указан родитель this, который и управляет его временем жизни.

после чего сокетом формируется сигнал ошибки и отправляется уже удаленному modbusDevice. И программа валится.

Все сигнал слот соединения разрываются и все сообщения для modbusDevice удаляются из очереди обработки при его удалении.
Поэтому ситуации "сокетом формируется сигнал ошибки и отправляется уже удаленному modbusDevice" при корректной реализации быть не может.

Здесь на лицо проблема конкурентного доступа к экземпляру объекта. Обработка сообщений происходит в одном потоке, удаление объекта в другом.
Можно проверить это с помощью определения своего типа производного QModbusRtuClient, например, и вывода и сравнении информации о потоке в деструкторе и обработчиках сигналов.

Вариантов управления временем жизни не так уж и много:

  • объект на стеке - удалиться при потере области видимости в том же потоке, где был создан, независимо от потока обработки событий
  • член класса - удалиться вместе с экземпляром агрегата, независимо от потока обработки событий
  • умный указатель - удалиться вместе удаления умного указателя, независимо от потока обработки событий
  • Qt parent-child отношение - удалиться вместе с экземпляром родителя, независимо от потока обработки событий
  • new/delete - удалиться в вместе вызова delete, независимо от потока обработки событий
  • deleteLater - удалиться в потока обработки событий, независимо от других способов владения (кроме Qt parent-chaild)


Основное, вроде, перечислил.
Почти любая суперпозиция способов владения - крах программы с похожей проблемой, как здесь.

Удаление, изменение и т.д. конфигурации не должно приводить в краху программы. Решение задачу с помощью "отложенное удаление старой конфигурации ...", лишь усугубит ситуацию, так как проблема никуда не денется, а частота её появления уменьшиться.




 28 
 : Апрель 04, 2024, 13:50 
Автор sergek - Последний ответ от sergek
Одна нормальная тема в год - и ту закрывает  Плачущий
Не вопрос, отменил)) Надо бы тогда тему как-то уточнить, чтобы обсуждение пошло в нужном русле.

 29 
 : Апрель 04, 2024, 12:57 
Автор sergek - Последний ответ от Igor_S
Для человека "вне (вашего) проекта" информативно это
...после чего сокетом формируется сигнал ошибки и отправляется уже удаленному modbusDevice. И программа валится.
И что, Qt позволяет вот так "отправить сигнал удаленному"? Не должно

Тему закрываю.
Зачем? Кому-то мешает?  Улыбающийся

Одна нормальная тема в год - и ту закрывает  Плачущий

 30 
 : Апрель 04, 2024, 11:35 
Автор sergek - Последний ответ от sergek
И пытаться как-то определить что поле QObjectPrivate * испорчено (ну хотя бы нечетный адрес). Придется подключить приватные хедеры.
Теперь, кажется, понятно - ловить событие от sender`а в receiver`а. Но что мы поймаем, если приемник уже разрушен? В том то и проблема, что мы цепочкой сигнал/слот можем управлять только со стороны объекта, который отправляет событие. А на стороне приемника мы не можем ничего сделать. Если бы соединение сигнал/слот мы бы могли отключать со стороны приемника, проблем бы не возникало.

Что-то подсказывает мне, что archiving никогда не удалится), цикл обработки событий уже не работает.
Удалится. Цикл в main еще работает в то время, как останавливаются потоки. Там у меня работает QtService, а вся программа выполнена в виде процесса.
Не поленился, проверил - деструктор archiving срабатывает (впрочем, я это и раньше проверял, просто убедился еще раз).

Конечно, хотелось бы увидеть весь проект или тестовый пример, или хотя бы стек вызовов по всем потокам.
Увы, сам проект ~50 тыс. строк, сделать минимальный пример - нехилая работа.
Но это уже и не требуется - проблему я локализовал. И она, как сразу мне подсказывали, в том, что "что receiver не живой".
Но пока не решил, что с этим делать.

В двух словах о проблеме, чтобы не было такого: "всем спасибо, все свободны" Улыбающийся.
У меня в составе ядра системы есть программные компоненты, отвечающие за взаимодействие с периферийными устройствами через аппаратные интерфейсы (usb, uart, i2c, ethernet и т.д.). В их задачу входит получение запросов от сервиса опроса или других, его преобразование в соответствии с прикладным протоколом (modbus, can, mqtt и т.д.) в raw-данные, передача в шину и получение ответа устройств. Что-то типа драйверов, я называю их контроллерами интерфейсов. Уверен, вы найдете более правильное название))

Крах программы наблюдается, когда я перед загрузкой новой конфигурации удаляю старые объекты контроллеров, использующих протоколы modbus rtu по протоколу TCP/IP. Это мой компонент (QModbusRtuClient), я сделал его на основе уже имеющихся в составе qtserialbus, исходники я публиковал где-то здесь. Ключевые фрагменты кода (не существенные части я пропускаю, отмечено '...'):

Код
C++ (Qt)
CModbusInterface::CModbusInterface(...) {
...
       //
       modbusDevice = new QModbusRtuClient(this);
...
}
 
CModbusInterface::~CModbusInterface(){
   if (modbusDevice) {
       modbusDevice->deleteLater();
   }
}
 
Объект modbusDevice реализует формирование запросов, передачу в шину, получение ответов и обработку ошибок. Думаю, фрагменты кодов тут не нужны - они есть в документации qt. Главное в том, что в этом объекте есть TCP-сокет, сигналы которого обрабатываются в CModbusInterface.

При удалении старой конфигурации удаляются объекты CModbusInterface. Если на шине все хорошо, все устройства отвечают (время реакции от нескольких мс до нескольких десятков мс), то удаление modbusDevice проходит успешно.
Но если какое-нибудь устройство перестает отвечать, включается механизм  таймаутов и повторов (ретрейнов) - это стандартное поведение компонетов modbus в qt. Т.е. если перед удалением контроллера мой запрос передан в шину, то он в modbusDevice болтается еще как минимум (1+numberOfRetries)*timeout - несколько секунд, после чего сокетом формируется сигнал ошибки и отправляется уже удаленному modbusDevice. И программа валится.

Изменить timeout и numberOfRetries перед удалением не удастся, т.к. они начинают действовать на следующий запрос, и никак не влияют на текущий.
Почему я особо отметил, что используется TCP-сокет: для последовательного порта в библиоеке используется QSerialPort::clear(QSerialPort::AllDirections), что, видимо, обеспечивает при удалении объекта очистку всех буферов и предотвращает формирование сигналов портом. По крайней мере, при работе через последовательные порты у меня программа не валится. Для сокета такой функции нет.

Как решить проблему? На вскидку есть пара вариантов: первый - отложенное удаление старой конфигурации, что-то вроде сборки мусора. Я так делал, мне не понравилось. Второй - не удалять старую конфигурацию, а ее изменять. Наверное, это вполне рабочий вариант, хотя и довольно нудный.

Вот теперь могу сказать: спасибо, коллеги, за помощь.

Страниц: 1 2 [3] 4 5 ... 10

Страница сгенерирована за 0.197 секунд. Запросов: 17.