Russian Qt Forum

Qt => Общие вопросы => Тема начата: QCasper от Октябрь 29, 2007, 14:37



Название: Падение QHttp в плагине
Отправлено: 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)


Название: Re: Падение QHttp в плагине
Отправлено: Tonal от Октябрь 29, 2007, 15:29
Как то здесь обсуждалось похожее.
Только там вроде простой сокет в плагине был.

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

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

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


Название: Re: Падение QHttp в плагине
Отправлено: QCasper от Октябрь 29, 2007, 15:40
Как то здесь обсуждалось похожее.
Только там вроде простой сокет в плагине был.

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

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

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

Эмм... не совсем я понял конечно. А поток то где создается? Не в плагине что-ли?


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

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

P.S. По поводу чего нельзя делать в коде загрузки/выгрузки dll-ек смотри Рихтера "Создание эффективных WIN32-приложений"


Название: Re: Падение QHttp в плагине
Отправлено: QCasper от Октябрь 29, 2007, 17:34
Понятно. Кстати в предыдущих версиях они таки ждали перед выгрузкой какой-то поток, и из-за этого после работы с таким плагином при попытке его замочить все висло намертво. Я об этом кстати и здесь писал и им писал. Они видно этот баг "пофиксили" и получили новый :)
Вынести коннект из плагина... То есть сделать так, чтобы приложение зависело от конкретного типа плагинов, придумать костыль, благодаря которому приложение должно определять, работает ли плагин с сокетами, и если да, то создавать ему этот сокет... Не самый хороший выход из положения на мой взгляд.


Название: Re: Падение QHttp в плагине
Отправлено: Tonal от Октябрь 30, 2007, 12:14
К сожалению идеальный мир не здесь. :-)

Таких мест как с сокетами есть некоторое количество во всех системах.
Например, если плагину нужно запустить поток или, не дай бог, с COM-ом поработать...


Название: Re: Падение QHttp в плагине
Отправлено: QCasper от Октябрь 30, 2007, 15:18
Один из плагинов этой системы работает с COM'ом как раз и запускает там потоки :)

По поводу топика, пообщался вчера с неким Дмитрием из рядов троллей, он потестил на линуксе у себя, говорит ниче не падает http://lists.trolltech.com/qt-interest/2007-10/thread00872-0.html.


Название: Re: Падение QHttp в плагине
Отправлено: Tonal от Октябрь 31, 2007, 09:22
А COM инициализируешь тоже в плугине?

В MSDN есть статья на тему, что можно и нельзя делать в коде загрузки/выгрузки http://msdn2.microsoft.com/en-us/library/ms682583.aspx


Название: Re: Падение QHttp в плагине
Отправлено: QCasper от Октябрь 31, 2007, 10:11
Да, в плагине. И поток (QThread) тоже создаю в плагине.


Название: Re: Падение QHttp в плагине
Отправлено: Tonal от Октябрь 31, 2007, 13:11
Значит просто повезло.
А с сокетами qt - нет. :-(


Название: Re: Падение QHttp в плагине
Отправлено: T800 от Ноябрь 07, 2007, 09:55
А если внести в систему методы плугина вроде InitPlugin - ClosePlugin, где все делать и вызывать их  из программы после и до выгрузки соответственно?,.


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

И чем будет заниматься, например, метод ClosePlugin?