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

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Падение QHttp в плагине  (Прочитано 7311 раз)
QCasper
Гость
« : Октябрь 29, 2007, 14:37 »

Есть плагин с таким содержимым:

Код:
plugin::plugin() {
m_Buffer = 0;
m_Http = new QHttp;

connect(m_Http, SIGNAL(requestFinished(int, bool)),
this, SLOT(requestFinished(int, bool)));
}
plugin::~plugin() {
if (m_Http) delete m_Http;
if (m_Buffer) delete m_Buffer;
}
void plugin::abort() {
m_Http->abort();
if (m_Buffer)
delete m_Buffer, m_Buffer = 0;
}
void plugin::post() {
QHttpRequestHeader header("POST", c_Path);
header.setContentType("text/xml");

m_Http->setHost(c_Host);

m_Buffer = new QBuffer;
if (m_Buffer->open(QIODevice::WriteOnly))
m_ID = m_Http->request(header, QByteArray("preved!"), m_Buffer);
else delete m_Buffer, m_Buffer = 0;

}
void plugin::requestFinished(int id, bool error) {
qDebug(qPrintable(QString("Request with ID %1 finished").arg(id)));

if (id != m_ID) return;

if (error) qDebug(qPrintable(m_Http->errorString()));

if (m_Buffer->isOpen())
m_Buffer->close();
delete m_Buffer, m_Buffer = 0;
}

Из программы, которая использует этот плагин, я вызываю сначала метод post(), а потом вызываю функцию unload::

Код:
void app::unload() {
   delete m_Plugin;
   m_Loader->unload();
   delete m_Loader;
}

где m_Plugin = qobject_cast<IPlugin*>(m_Loader->instance());
проблема в том, что приложение после вызова функции с таким кодом падает с access violation.

Интересным моментом является тот факт, что если вызвать функцию unload до вызова post(), то никаких падений не происходит, класс плагина уничтожается, плагин нормально выгружается.

Полный код с файлами проектов для msvc можно взять здесь: http://www.creobyte.com/tools/qhttp_bug.rar (~7.52k)
« Последнее редактирование: Октябрь 29, 2007, 15:12 от QCasper » Записан
Tonal
Гость
« Ответ #1 : Октябрь 29, 2007, 15:29 »

Как то здесь обсуждалось похожее.
Только там вроде простой сокет в плагине был.

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

Решением было создание первого сокета в главном потоке.

P.S. И кажется мне, что это только под виндой происходило...
Записан
QCasper
Гость
« Ответ #2 : Октябрь 29, 2007, 15:40 »

Как то здесь обсуждалось похожее.
Только там вроде простой сокет в плагине был.

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

Решением было создание первого сокета в главном потоке.

P.S. И кажется мне, что это только под виндой происходило...

Эмм... не совсем я понял конечно. А поток то где создается? Не в плагине что-ли?
Записан
Tonal
Гость
« Ответ #3 : Октябрь 29, 2007, 17:12 »

Цитировать
-Повторяю ещё раз, рация на бронепоезде! (c) Василий Иванович
Потоки как бы ортогональны плагинам и прочим динамическим библиотекам.
Поток создаётся при конекте сокета (QHostInfoAgent).
При выгрузке плагина, этот поток нужно завершить, вот тут-то грабля и зарыта - из кода выгрузки dll нельзя вызывать функции ожидания. Похоже Троли пытались это как-то обойти и получили AV.

Так что лучший выход - это вынести создание и коннект сокета из плугина.
Ну и отослать баг тролям...

P.S. По поводу чего нельзя делать в коде загрузки/выгрузки dll-ек смотри Рихтера "Создание эффективных WIN32-приложений"
Записан
QCasper
Гость
« Ответ #4 : Октябрь 29, 2007, 17:34 »

Понятно. Кстати в предыдущих версиях они таки ждали перед выгрузкой какой-то поток, и из-за этого после работы с таким плагином при попытке его замочить все висло намертво. Я об этом кстати и здесь писал и им писал. Они видно этот баг "пофиксили" и получили новый Улыбающийся
Вынести коннект из плагина... То есть сделать так, чтобы приложение зависело от конкретного типа плагинов, придумать костыль, благодаря которому приложение должно определять, работает ли плагин с сокетами, и если да, то создавать ему этот сокет... Не самый хороший выход из положения на мой взгляд.
Записан
Tonal
Гость
« Ответ #5 : Октябрь 30, 2007, 12:14 »

К сожалению идеальный мир не здесь. :-)

Таких мест как с сокетами есть некоторое количество во всех системах.
Например, если плагину нужно запустить поток или, не дай бог, с COM-ом поработать...
Записан
QCasper
Гость
« Ответ #6 : Октябрь 30, 2007, 15:18 »

Один из плагинов этой системы работает с COM'ом как раз и запускает там потоки Улыбающийся

По поводу топика, пообщался вчера с неким Дмитрием из рядов троллей, он потестил на линуксе у себя, говорит ниче не падает http://lists.trolltech.com/qt-interest/2007-10/thread00872-0.html.
Записан
Tonal
Гость
« Ответ #7 : Октябрь 31, 2007, 09:22 »

А COM инициализируешь тоже в плугине?

В MSDN есть статья на тему, что можно и нельзя делать в коде загрузки/выгрузки http://msdn2.microsoft.com/en-us/library/ms682583.aspx
Записан
QCasper
Гость
« Ответ #8 : Октябрь 31, 2007, 10:11 »

Да, в плагине. И поток (QThread) тоже создаю в плагине.
Записан
Tonal
Гость
« Ответ #9 : Октябрь 31, 2007, 13:11 »

Значит просто повезло.
А с сокетами qt - нет. :-(
Записан
T800
Гость
« Ответ #10 : Ноябрь 07, 2007, 09:55 »

А если внести в систему методы плугина вроде InitPlugin - ClosePlugin, где все делать и вызывать их  из программы после и до выгрузки соответственно?,.
Записан
QCasper
Гость
« Ответ #11 : Ноябрь 07, 2007, 10:00 »

А если внести в систему методы плугина вроде InitPlugin - ClosePlugin, где все делать и вызывать их  из программы после и до выгрузки соответственно?,.

И чем будет заниматься, например, метод ClosePlugin?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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