Название: Работа с dll во втором потоке Отправлено: vaychick от Май 23, 2011, 16:26 Здравствуйте, есть ф-я которая в цикле вызывает ф-и динамически подгружаемой dll, задача была вынести эту ф-ю в отдельный поток - вынес, но есть проблема при обращении к функциям dll приложение вылетает с SIGSERV - Segmentation fault. Причем если убрать вызовы этих dll ф-й все работает нормально.
Собственно вопрос, какие есть подводные камни при использовании dll во втором потоке, 2 дня бъюсь и никак не могу найти причину вылета программы. Причем без вызова dll поток нормально стартует, работает и завершается. Та же самая dll с теми-же ф-ми работала стабильно в главном потоке. Реализовал второй поток след. образом: Внутри наследника QThread, создается объект который работает с dll, он переносится во второй поток методом moveToThread, затем стартует цикл обработки событий, а ф-я которая крутит цикл, это слот, который вызывается после посылкой сигнала извне. исходный код не привожу, так как из контекста его трудно достать, если нужно будет выложу. Могу кратко описать логику в псевдокоде Код: class thread : public QThread { dll пробовал грузить и в конструкторе (main thread) и внутри foo() если закоментировать вызов dllFoo и самому модифицировать someMember-ры, то все нормально, создается впечатление что dll что-то внутри себя делает, что конфликтует с потоками, пробовал обрамлять вызов dllFoo в mutex.lock() \ unlock(), эффекта нет. Примечательно то, что ф-и из dll не используются в основном потоке, и свойства someMember так-же не используются, мотивов для блокировок я не вижу, приложение просто вылетает после вызова ф-й dll. Причем dll обращается к внешнему устройству и более никак не связано с приложением. читал тут http://habrahabr.ru/blogs/qt_software/115830/ (http://habrahabr.ru/blogs/qt_software/115830/) и сдесь на форуме и документацию Qt, поэтому кажеться какбудто поток организован верно, хотя я могу ошибаться. Кажется будто причина в dll, такое может быть? если да, то какие меры можно предпренять? Название: Re: Работа с dll во втором потоке Отправлено: twp от Май 23, 2011, 17:14 по ходу QLibrary создается в главном потоке и не переносится (как Worker) в рабочий поток
Название: Re: Работа с dll во втором потоке Отправлено: xokc от Май 23, 2011, 20:14 Честно говоря ни разу не имел проблем с загрузкой DLL из не основного потока. Видимо проблема именно в Вашей dll.
Название: Re: Работа с dll во втором потоке Отправлено: vaychick от Май 24, 2011, 08:13 по ходу QLibrary создается в главном потоке и не переносится (как Worker) в рабочий поток Но ведь она часть объекта Worker. Я пробовал и другой вариант, непосредственно в foo() подгружать dll: void foo() { QLibrary dll2("dllPath"); dll2.load(); if(!(dllFoo = (dllFooProto)dll2.resolve("dllFoo"))) qDebug() << "error"; while(1) { QCoreApplication::processEvents(); if(isExit) return;//Внешнее событие устанавливает флаг для выхода из цикла Sleep(1000); dllFoo(someMember, &someMember2, &someMember3);//Ф-я модифицирует содержимое someMember2 и someMember3 } } добавлю так-же что Worker не имеет предка, но наследуется от абстрактного класса, поэтому мне кажется, что должно переноситься нормально методом moveToThread Цитировать Честно говоря ни разу не имел проблем с загрузкой DLL из не основного потока. Видимо проблема именно в Вашей dll. Тоже начинаю об этом думать, но dllFoo просто обращается к устройству и считывает из него поток байтов в someMember, какие коллизии могут создаться из-за многопоточности не понимаюНазвание: Re: Работа с dll во втором потоке Отправлено: twp от Май 24, 2011, 09:33 по ходу QLibrary создается в главном потоке и не переносится (как Worker) в рабочий поток Но ведь она часть объекта Worker. Я пробовал и другой вариант, непосредственно в foo() подгружать dll: void foo() { QLibrary dll2("dllPath"); dll2.load(); if(!(dllFoo = (dllFooProto)dll2.resolve("dllFoo"))) qDebug() << "error"; while(1) { QCoreApplication::processEvents(); if(isExit) return;//Внешнее событие устанавливает флаг для выхода из цикла Sleep(1000); dllFoo(someMember, &someMember2, &someMember3);//Ф-я модифицирует содержимое someMember2 и someMember3 } } добавлю так-же что Worker не имеет предка, но наследуется от абстрактного класса, поэтому мне кажется, что должно переноситься нормально методом moveToThread Название: Re: Работа с dll во втором потоке Отправлено: Igors от Май 24, 2011, 09:42 Не вижу причем тут moveToThread - хоть бы и вообще ничего не переносили, слот должен работать. Разумеется Вы убедились что в главной нитке dllFoo работает нормально. Я бы начал интересоваться
- отключить весь остальной код слота (оставить только вызов dllFoo) - какой адрес возвращает resolve (сравнить его с возвращаемым в главной) - стеком краша - вошла ли она в dllFoo и где рухнула Если это Вындоуз - убедиться что dll создана как "Multithreaded (Debug) DLL" Название: Re: Работа с dll во втором потоке Отправлено: SASA от Май 24, 2011, 10:05 А когда происходит соединение со слотом void foo()? Может надо точно указать тип соединения?
Название: Re: Работа с dll во втором потоке Отправлено: vaychick от Май 24, 2011, 13:36 Цитировать согласно документации moveToThread переносит объект и его детей, но поскольку в конструктор QLibrary не был передан Worker как родитель, то dll не был перенесен в поток вместе с Worker и остался в главной потоке. Кроме того, в потоке используется Sleep. Может проблема не в нем, но не понятно почему не используется QThread::msleep, QThread::sleep или QThread::usleep. Спасибо за информацию насчет переноса свойств объекта, но сейчас тестирую когда dll грузится прям в слоте. Я не использовал QThread::sleep потому, что Worker не унаследован от QThread, и "не знает" что он свойство класса thread, поэтому использую системныю ф-ю sleep, без вызова dllFoo цикл крутиться нормально. Цитировать Не вижу причем тут moveToThread - хоть бы и вообще ничего не переносили, слот должен работать. Разумеется Вы убедились что в главной нитке dllFoo работает нормально. Да, в главном потоке, точнее вообзе без потоков, работало нормально, пока не начал переделывать.Цитировать - отключить весь остальной код слота (оставить только вызов dllFoo) - какой адрес возвращает resolve (сравнить его с возвращаемым в главной) - стеком краша - вошла ли она в dllFoo и где рухнула Реальный код, который сейчас тестирую Код: void ReaderCOM::pollReader() { вывод: Код: Gen2MultiTagIdentify: "1b621b50" "?" - наверное потому, что на третьей итерации вылетает Отладчик показывает на это место SIGSERV Код: QTextStream &QTextStream::operator<<(const QString &string) я выводил адреса gen2MultiTagIdentify в конструкторе(основной поток) и в цикле, перед вызовом qDebug() << "Gen2MultiTagIdentify:", они совпадают Притом вылет происходит на 3-й итерации цикла, а не на первой. Притом если ничего ны выводить в лог - вылетает все равно Название: Re: Работа с dll во втором потоке Отправлено: vaychick от Май 24, 2011, 13:38 Код: А когда происходит соединение со слотом void foo()? Может надо точно указать тип соединения? Название: Re: Работа с dll во втором потоке Отправлено: Igors от Май 24, 2011, 15:58 Для начала проверить на битую кучу (инструмент зависит от платформы/компилятора). Затем углубляться в изучение dll - в первую очередь какие сигналы она испускает, и могут ли они навредить если посланы из др. нитки
Название: Re: Работа с dll во втором потоке Отправлено: blood_shadow от Май 24, 2011, 17:04 Для начала проверить на битую кучу (инструмент зависит от платформы/компилятора) а с помощью mingw в среде Creator'а как такое сделать?Название: Re: Работа с dll во втором потоке Отправлено: vaychick от Май 25, 2011, 08:16 Цитировать Для начала проверить на битую кучу (инструмент зависит от платформы/компилятора). Затем углубляться в изучение dll - в первую очередь какие сигналы она испускает, и могут ли они навредить если посланы из др. нитки Я честно говоря не в курсе, что за сигналы в DLL, но хочу сказать что dll сторонняя и скомпилирована Microsoft Visual C++ 6.0 DLL, как показал PEid Название: Re: Работа с dll во втором потоке Отправлено: Igors от Май 25, 2011, 13:54 а с помощью mingw в среде Creator'а как такое сделать? Никогда не пользовался этой IDE, поэтому здесь подсказать не могу.Я честно говоря не в курсе, что за сигналы в DLL, но хочу сказать что dll сторонняя и скомпилирована Microsoft Visual C++ 6.0 DLL, как показал PEid Надо убедиться что начиная от вызова ф-ции dll и до краша управление нигде не отдается Вам. Если таких callback'ов нет, то пора сделать вывод что это проблема конкретной dll и сосредлточиться на поиске ее новой версии (или переносе вызовов в главную нитку)Название: Re: Работа с dll во втором потоке Отправлено: vaychick от Май 25, 2011, 16:02 Цитировать Надо убедиться что начиная от вызова ф-ции dll и до краша управление нигде не отдается Вам. Если таких callback'ов нет, то пора сделать вывод что это проблема конкретной dll и сосредлточиться на поиске ее новой версии (или переносе вызовов в главную нитку) На данный момент приложение падает, через несколько инструкций после того, как вызов ф-и из dll отработает, dll весит 63 килобайта и работает с COM портом, начал задумываться о том, чтобы реализовать самому эти ф-и, но пока не могу найти точной спецификации |