Название: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 10:27 Здравствуйте!
Имеется набор оборудования, которое надо протестировать. Исправность одного вида оборудования от исправности другого не зависит, поэтому собираюсь запускать тестирование в отдельных потоках (для тестирования каждого вида устройств пишется отдельный класс, наследник QThread). Оборудование может быть слегка глюкавое и завешивать тестирующую программу (например, долго не отвечать по портам и т.п.) поэтому надо предусмотреть "аварийную" остановку и выход из потоков. Проверку выхода по времени собираюсь осуществлять "извне", т.е. не из самих класов на основе QThread. Однако собственно выход мне пока приходит в голову только по terminate(). Можно ли всё-таки каким-то образом заставить поток остановиться "на середине" и при необходимости "почистить" за собой? Возможно повторное тестирование и применять метод terminate() мне немного неуютно. (Отмечу, что никакие мьютексы и семафоры не используются, также внутри потоков петля событий методом exec() не запускается). Могу выложить уже написанный код. Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 22, 2012, 10:54 Мб тебе стоит подумать об плагинах, или отдельных приложениях?
В результате тебе нужно будет написать программу - менеджера и по программе/плагину для каждого оборудования. И при падении/зависании одного не будет массовых репрессий. Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 10:55 Выложу всё-таки наваянное. (Как-то не уверен в том, что написано хорошо)
Код: #ifndef ABSTRACTITEMTESTING_H Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 11:00 Мб тебе стоит подумать об плагинах, или отдельных приложениях? В результате тебе нужно будет написать программу - менеджера и по программе/плагину для каждого оборудования. И при падении/зависании одного не будет массовых репрессий. Скажу откровенно - это пока для меня сложновато будет. Как я понимаю, вместо потоков надо использовать процессы (в заглавном сообщении везде поменял все встретившиеся "процессы" на "потоки"). Но и сейчас, вроде бы, не должно быть каких-то особенных репрессий - по истечении срока потоки останавливаются. Вопорс в повторном тестировании и "уборке за собой". Будет ли это проще с процессами? Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 22, 2012, 11:01 Возможно повторное тестирование и применять метод terminate() мне немного неуютно. "Неуютно" - не то слово :) Эта задача частенько мелькает - "зависает" какой-то внешний вызов. Как это решить средствами языка - не знаю. Возможно придется задействовать дустhttp://www.boost.org/doc/libs/1_51_0/libs/exception/doc/tutorial_exception_ptr.html (http://www.boost.org/doc/libs/1_51_0/libs/exception/doc/tutorial_exception_ptr.html) Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 11:05 По ссылке 404 выдает.
(Может, сделать в классах-тестировщиках какие-то особые "подчищающие" функции, которые будут вызываться после терминации процесса? Функция getName()-то работает). Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 11:06 А впрочем, ссылка исправилась )) Почитаю...
Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 22, 2012, 11:13 То я криво скопировал, исправил. Да, "чиститься" нужно, но для этого нужно получить exception чтобы стек раскрутился. Др варианты явно хуже
- terminate может не сработать вообще - процессы вместо ниток - ну это тащить "корову на баню" и уродовать всю нормальную логику приложения Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 11:18 Кстати - это мне кажется, или действительно на официальном сайте Qt в главе о стиле программирования не рекомендовано применять try с exception? ^____^
Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 22, 2012, 11:22 Кстати - это мне кажется, или действительно на официальном сайте Qt в главе о стиле программирования не рекомендовано применять try с exception? ^____^ Иногда приходится жертвовать "стилем" чтобы достичь нужного. Да и сами Qt никогда не утверждали что их стилю нужно следовать неукоснительно и спокойно/нормально относятся к исключениямНазвание: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 22, 2012, 12:07 Если спроектировать потоки правильно и поместить все проверки длительности запросов и прочая в них, тогда потоков вполне хватит.
Terminate - фу, кака. У меня оно однажды закадычно продолжало поток до посинения, вешая программу. PS По идее, поток виснуть не должен при любой ситуации. Т.е. чтоб его положить нереально было входными данными - вот как надо сделать и тогда будет чики-пуки. PPS внешние вызовы это плохо, особенно если они синхронные. Название: Re: Потоки при параллельном тестировании оборудования Отправлено: xokc от Август 22, 2012, 12:29 А если там, где-то внутри потока в чужом коде GPF исключение сгенерится - тогда как? Приложению таки смерть придёт?
Имею ввиду вот эту статью (http://habrahabr.ru/post/131412/) и комменты к ней. Нам в своё время приходилось разрабатывать сервер приложений, который внутри своих потоков (1 поток на одного клиента - клиентов мало, такая модель устраивала) должен был использовать чужие dll. Ничего умнее не придумали, чем от потоков уйти к процессам, т.к. код внутри dll периодически глючил, насмерть убивая сервер, а так - умер процесс, дак туда ему и дорога. Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 22, 2012, 13:02 Вот собственно потому я и советовал в начале темы перейти на процессы ;) Там не страшно, если отвалится.
Другой вопрос, что если вся программа своя, тогда потоки спокойно будут выполнять свои обязанности :) Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 14:06 Ну, программа своя, да оборудование не свое и драйверы к нему - тоже. Так что хотелось бы подстраховаться...
Я, собственно, изначально пытался возложить обязанность останова тестирования на сам класс-наследник QThread. Завел в нем ван-шот от таймера в методе run() с вызовом метода "зачистки и остановки", но у меня ничего не вышло. Петли событий-то нету в общем случае и метод по истечении срока не запускался. Скажите, а если грохнуть класс-наследник delet'ом, а после вызвать какой-нибудь "уборщик"? UPDATE: Программа, собственно, не падала и не вываливалась - она завешивалась долгим ожиданием и реакцией железа. Нарушений с памятью и сегментацией, скорее всего, ждать не нужно. Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 22, 2012, 14:14 Скажите, а если грохнуть класс-наследник delet'ом, а после вызвать какой-нибудь "уборщик"? Так если он висит то грохнуть можно только из др нитки - верный крашНазвание: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 22, 2012, 14:18 Что мешает вам самим в потоках проверять время выполнения ваших же функций? Что мешает поставить стража на остановку?
PS или я чего то незнаю, или я чего т не понимаю :) Название: Re: Потоки при параллельном тестировании оборудования Отправлено: xokc от Август 22, 2012, 14:27 У него висит вовремя выполнения чужих функций из драйверов устройств. Типа readData() - и на ней нитка и умерла. И прервать этот самый readData не получается.
Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 14:34 xokc прав - примерно это и происходит.
А как реализовать "стража"? Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 22, 2012, 14:37 Страж = булевский флаг, но в зависоне он бесполезен.
Если такая ситуация, то отдельные процессы - это простое и вместе с тем хорошее решение. Никаких забот о мусоре и прочем. Отработал и прислал данные - молодец. Работает 2 часа подряд - убил процесс и усё нормально, выдал ошибку юзверю. Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 14:45 Скажите, а если грохнуть класс-наследник delet'ом, а после вызвать какой-нибудь "уборщик"? Так если он висит то грохнуть можно только из др нитки - верный крашДа, грохаем из другой нитки. Правда, я надеялся, что в деструкторе можно будет освободить какие-нибудь переменные, порт закрыть, не? ^___^ Вы, кстати, согласны, что при зависе надежнее работать с процессами, а не с потоками? Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 14:46 Страж = булевский флаг, но в зависоне он бесполезен. Если такая ситуация, то отдельные процессы - это простое и вместе с тем хорошее решение. Никаких забот о мусоре и прочем. Отработал и прислал данные - молодец. Работает 2 часа подряд - убил процесс и усё нормально, выдал ошибку юзверю. Спасибо. Надо будет обмозговать и рассмотреть возможность реализации :) Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 22, 2012, 14:55 Поток, грохнутый terminate продолжает работать ещё некоторое время. В некоторых случаях (у меня было) он продолжает писать данные, при этом вроде - бы являясь уже убитым :D Чуть не поседел, пока искал среди 2 потоков ошибку, а третий, убитый, весело менял им данные и грохал программу :D
Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 22, 2012, 15:16 Да, грохаем из другой нитки. Правда, я надеялся, что в деструкторе можно будет освободить какие-нибудь переменные, порт закрыть, не? ^___^ Вызов delete не прервет выполнение нитки нормально "зато" искалечит данные к которым она обратитсяВы, кстати, согласны, что при зависе надежнее работать с процессами, а не с потоками? Ну это решение просто "потому что нет нормального", всем понятно что оно "через задницу". Я бы прорывался через дуст о котором высокого мнения - хотя и редко его использовалНазвание: Re: Потоки при параллельном тестировании оборудования Отправлено: xokc от Август 22, 2012, 15:35 Я бы прорывался через дуст о котором высокого мнения - хотя и редко его использовал А чем это может помочь прервать зависший вызов?Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 22, 2012, 15:46 Я бы прорывался через дуст о котором высокого мнения - хотя и редко его использовал А чем это может помочь прервать зависший вызов?Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 22, 2012, 15:51 Эммм... А откуда она получит исключение?
Я просто не особо осведомлён о возможностях "дуста", но как он может по результату проверки (долгое время выполнения и прочая лабуда типа устройство зациклилось) выдать ексцепшн до окончания обработки вызова? Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Odyssey от Август 22, 2012, 15:53 Я пока вынужден работать на Qt 4.5.3 под слегка подуродованную версию Линукс (правда, скоро возможен переход на 4.8.2). Boost там работать станет?
И винюсь - пока не очень разобрался в принципе действия. Классу кто-то извне кинет исключение? Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 22, 2012, 16:17 Я пока вынужден работать на Qt 4.5.3 под слегка подуродованную версию Линукс (правда, скоро возможен переход на 4.8.2). Boost там работать станет? Не знаю. Я просто скопировал фолдер дуста, добавил путь в проект и все, с пол-пинка пошло и на Mac и на Вындоуз.И винюсь - пока не очень разобрался в принципе действия. Классу кто-то извне кинет исключение? Смысл что если нитка получит исключение - она попадет на Ваш catch, там и зачищайтесь и цивильно выходите. Слышал предлагают это даже добавить в стандарт языка - именно по тем соображениям что Вы изложили (борьба с зависоном). Хз, может в С++ 11 уже добавили (где же эрудиты когда они нужны) ???Сам не делал (пока не припекло) но присматривался - это есть в Вындоуз (но это 1 платформа) и в дусте. Название: Re: Потоки при параллельном тестировании оборудования Отправлено: xokc от Август 22, 2012, 16:37 Классу кто-то извне кинет исключение? Смысл что если нитка получит исключение - она попадет на Ваш catch, там и зачищайтесь и цивильно выходите.Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 22, 2012, 16:41 Igors, ловля исключения даже чужого реализована в С++. Это банальный try/catch.
Но оно работает, если в чужом коде кто-то его бросает. А если чужой код завис к чертям, то не поможет уже ничего :/ Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 22, 2012, 17:29 Давайте еще раз. Внутри метода run в наследнике QThread "завис" метод read из чужой dll. Завис тупо - без таймаутов и exception. Кто в этом случает сгенерит это самое исключение, которое потом будет передано через boost основному потоку? Я сам (т.е. прерывающий зависание) напр в главной нитке. "Просто так" это ничего не даст потому что на др нити это никак не повлияет. Речь идет о механизме передачи exception в др нити.Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 22, 2012, 19:12 Эмм.. Igors а зачем?
ТС же ясно сказал - тесты независимые. Каждый тест отдельная нить. Если нить зависает, её надо прибить без последствий и выдать ошибку. Exception'ов внутри внешних вызовов нет. Виснет вся нить, что делать? :) Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 22, 2012, 19:20 Эмм.. Igors а зачем? Знову за рибу грошi :'( Нет способа "прибить без последствий", но можно снять ее с ожидания передав ей exception "извне". Это совсем не ново, вот напр один клепал, правда под ВындоузТС же ясно сказал - тесты независимые. Каждый тест отдельная нить. Если нить зависает, её надо прибить без последствий и выдать ошибку. Exception'ов внутри внешних вызовов нет. Виснет вся нить, что делать? :) http://www.codeproject.com/Articles/71529/Exception-Injection-Throwing-an-Exception-in-Other (http://www.codeproject.com/Articles/71529/Exception-Injection-Throwing-an-Exception-in-Other) Название: Re: Потоки при параллельном тестировании оборудования Отправлено: xokc от Август 23, 2012, 08:20 То есть, нужно придумать неких диспетчер потоков, который анализирует работоспособность (независшесть) каждой из нитей и в случае проблем с ней генерит для неё exception, "проталкивает" его внутрь нити, нить самостоятельно завершается, всё за собой подчищает и сообщает об этом диспетчеру. При этом основное приложение живёт нормальной жизнью.
Как-то уж больно заманчиво всё это выглядит, чтобы уже не быть реализованным в виде готового решения. Что касается C++ 0x, то вот цитата от Страуструпа (там, вообще много интересного http://sergeyteplyakov.blogspot.com/2012/05/c-11-faq.html): Не существует возможности запросить поток завершить исполнение (например, потребовать его завершиться как можно быстрее и насколько возможно безопасно), или принудительно прервать его исполнение (т.е. убить его). Мы оставили следующие возможности для реализации такого поведения: - Разработать собственный механизм кооперативный отмены исполнения (с помощью разделяемых данных, вызывающий поток может установить значение, которое будет прочитано вызываемым потоком для быстрого и безопасного завершения), - С помощью «нативного подхода» (получив доступ к дескриптору операционной системы с помощью thread::native_handle()), - Завершить процесс (с помощью std::quick_exit()), - Завершить программу (с помощью std::terminate()). Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Bepec от Август 23, 2012, 09:27 Igors, а можно маленький примерчик с комментариями? В виде проекта допустим?
Очень уж заманчиво выглядит как бэ. Название: Re: Потоки при параллельном тестировании оборудования Отправлено: Igors от Август 23, 2012, 14:38 То есть, нужно придумать неких диспетчер потоков, который анализирует работоспособность (независшесть) каждой из нитей и в случае проблем с ней генерит для неё exception, "проталкивает" его внутрь нити, нить самостоятельно завершается, всё за собой подчищает и сообщает об этом диспетчеру. При этом основное Именно. Все корректно/легальноприложение живёт нормальной жизнью. Как-то уж больно заманчиво всё это выглядит, чтобы уже не быть реализованным в виде готового решения. Дуст - вполне авторитетный источник. Эту ссылку я уже приводил, но наверное затерялась :)http://www.boost.org/doc/libs/1_39_0/libs/exception/doc/tutorial_exception_ptr.html (http://www.boost.org/doc/libs/1_39_0/libs/exception/doc/tutorial_exception_ptr.html) Судя по первой фразе - реализовано. Дальше правда надо вникать тшательно, ну дело того стоит Igors, а можно маленький примерчик с комментариями? В виде проекта допустим? Не понял, а у кого правая рука Вындоуз, у Вас или меня? Ну вот Вам и карты в рукиОчень уж заманчиво выглядит как бэ. http://msdn.microsoft.com/en-us/library/dd293602.aspx (http://msdn.microsoft.com/en-us/library/dd293602.aspx) Название: Re: Потоки при параллельном тестировании оборудования Отправлено: xokc от Август 24, 2012, 09:20 Дуст - вполне авторитетный источник. Эту ссылку я уже приводил, но наверное затерялась :) Я немного другое имел ввиду. Хотелось бы видеть реализацию не пробрасывания exception из потока в поток, а весь функционал в виде готового "зависоустйчивого" диспетчера. Наверняка в рамках какого-нибудь из opensource проектов уже всё сделано.Судя по первой фразе - реализовано. Дальше правда надо вникать тшательно, ну дело того стоит |