|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
Всех с наступившим! Есть задача использования COM разных версий одной и той же компоненты в dll библиотеке (COM сервер). Версии прекрасно работают по отдельности, но если сначала загрузить одну (версия 1), потом загрузить другую (версия 2), и попытаться с ними работать (в разных потоках или по очереди), то я словлю краш и ошибки будут каждый раз разные, в зависимости от того, в каком состоянии находится в данный момент память/стек, или что там от них осталось после попытки совместить несовместимое. Я не ставлю себе задачу отладки падения - компонента не моя и исходников у меня нет. Я просто хочу обойти проблему за счет корректного освобождения COM ресурсов. Идея следующая. - в потоке создаем инфраструктуру COM : CoInitializeEx(..multi threaded appartment..) - создаем IDispatch компоненты первой версии (INPROC_SERVER) - используем простой вызов одной команды с одним параметром (GetIDsOfNames + Invoke) - чистим ресурсы, если использовались - освобождаем IDispatch - Release - освобождаем COM CoUnitialize Затем повторяем все те же шаги, только для компоненты версии 2. По идее, версия компоненты №1 после деинициализации COM должна быть выгружена и не мешать работе компоненты версии №2. Написал простейшую тестовую программу (чтобы исключить все побочные эффекты). Весь код живет в потоке main. По началу у меня ничего не вышло, так как COM цеплялся в процесс и не хотел выгружать dll компоненты, даже после вызова CoUnitialize. Все остальные данные были корректно почищены, IDispatch->Release возвращал 0. После непродолжительного копания, я решил попробовать отключить кэширование строк и сразу после инициализации COM инфраструктуры воткнул вызов SetOaNoCache . И все заработало ! Я пробовал по-разному: вызывал сначал код первой версии, потом второй, потом снова первой - стабильно! Ничего не падает, COM освобождается, все ок. Вчера работало, сегодня с утра - тоже. Код тестовой программы с тех пор не менял , занимался переносом алгоритма в рабочую версию приложения. Сейчас решил еще разок протестить, т.к. понадобилось перепроверить несколько моментов. И код, который я не менял , вдруг перестал работать! Тестовая машина не перезагружалась (я не исключаю, что после перезагрузки он снова начнет работать, поэтому пока не трогаю ее) Что же изменилось? Во время отладки я вижу, что после использования первой версии компоненты, после очистки COM ресурсов, ее dll продолжает спокойно висеть у меня в процессе , поэтому когда приходит время загружать вторую версию происходит конфликт и код крашится. Я не понимаю, почему код, который не менялся и прекрасно проходил тесты два дня назад, начал выдавать такие перлы? В связи с чем я хочу попросить помощи в решении нескольких вопросов: Есть ли возможность заставить CoUnitialize принудительно выкинуть из моего процесса освобожденные ресурсы? Есть ли гарантированный способ очистки COM ресурсов? Возможно есть способ создания COM песочницы, которую потом можно спокойно помножить на ноль (отдельный процесс, увы, не вариант)? Возможно у вас есть какой-то свой вариант как можно решить данную задачу. -------------------------------------------------------------- o(O_O)o ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2019, 21:56 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
нашел в книге Don Box'a упоминание об CoFreeUnusedLibraries . Задействовал так Код: plaintext 1. 2.
проблема ушла, компонента выгружается. Завтра еще потестирую, почему-то неверится пока что опять какая-нибудь хрень не выстрелит ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2019, 22:26 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
нет, не работает. когда как - из 10 раз может 8 отработать нормально, но на 9 повалится ищем дальше... ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2019, 22:45 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
Ну, начнём с наиболее тривиального: ты в курсе, что IUnknown это интерфейс с подсчётом ссылок и освобождается когда счётчик падает до нуля? Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2019, 23:15 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
само собой, поэтому и написал, что CerebrumВсе остальные данные были корректно почищены, IDispatch->Release возвращал 0. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2019, 23:27 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
Вторя по глупости идея: а не имеют ли разные версии этого интерфейса одинаковые CLSID? Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2019, 23:38 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
гарантированно разные ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2019, 23:53 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
Значит что-то реально не так, такие объекты по идее должны без проблем сосуществовать (если случайно не пересеклись по третьему ресурсу). DrMemory или valgrind не пробовал напустить на тестовую программу? Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
06.01.2019, 23:59 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
Я думаю проблема, скорее всего, в том что, когда компонента разворачивает свою инфраструктуру, то она может успеть запульнуть что-то побочное (проверки себя любимой, записи в лог, что-то еще, что известно только ей), что не относится к моей задаче и что, в конечном итоге, не успевает остановиться/деинициализировать себя, когда я пытаюсь погасить COM принудительно. С моей стороны утечек точно нет, а вот со стороны компоненты есть незавершенные внутренние процессы. Я наблюдаю их иногда по косвенным признакам. Я больше чем уверен, если я оставлю таймаут между вызовами минут этак 10-20 все будет работать идеально, но это тоже не вариант, так как таких переключений мне надо сделать около 6-10 (на одну задачу/запрос, а задач может быть тысячи), прежде чем определиться с нужной версией и принять окончательное решение. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.01.2019, 00:06 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
Cerebrumона может успеть запульнуть что-то побочное Я об этом тоже как раз подумал. Если она что-то запускает в фоне, то должна иметь и метод это принудительно остановить. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
07.01.2019, 00:09 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovЗначит что-то реально не так, такие объекты по идее должны без проблем сосуществовать (если случайно не пересеклись по третьему ресурсу). DrMemory или valgrind не пробовал напустить на тестовую программу? нет, не пробовал. исходников компоненты у меня все равно нет, что я там увижу (увы, я не ассемблерщик)... Отладчик windbg говорит, что все стеки потоков компоненты в моем процессе в момент падения под подозрением в корректности. Падение происходит где-то в недрах библиотек, которую использует сама компонента. Ошибка же, точнее адрес, по которому происходит последнее обращение, все время разный, соответственно и ошибка может быть все время разной. Если адреc "мелкий", то это может быть Privileged Instruction или Invalid Instruction (вызов функции в компоненте попал в привилегированную область памяти), в остальном это банальный Access Denied с произвольным адресом, от 0x000000 до 0xFFFFFFFF, как повезет. Я точно знаю, что так происходит из-за переключения версий компонент (разработчик прямо заявляет о том, что нельзя использовать одновременно разные версии). По отдельности - они работают без нареканий. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.01.2019, 00:21 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovЯ об этом тоже как раз подумал. Если она что-то запускает в фоне, то должна иметь и метод это принудительно остановить. Разработчик увы не сообщает таких деталей В его логике ты должен сразу знать какую версию надо использовать - и точка. То что пытаюсь сделать я с его позиции - грязный хак. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.01.2019, 00:23 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
CerebrumОтладчик windbg говорит, что все стеки потоков компоненты в моем процессе в момент падения под подозрением в корректности. Падение происходит где-то в недрах библиотек, которую использует сама компонента. Это вполне могут быть всего лишь последствия, а DrMemory покажет причину: изначальное кривое обращение к памяти. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
07.01.2019, 01:42 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov, ну покажет ..., и что он там разберёт без отладочных файлов? ТС явно странного хочет, если без исходников компонент - это откровенный мазохизм ... |
|||
:
Нравится:
Не нравится:
|
|||
08.01.2019, 11:22 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
kealon(Ruslan), Если бы я хотел заставить работать две версии одновременно - вот тогда да, я сам себе злобный дурак. Но я же хочу сначала попользоваться одной версией, затем аккуратно ее выгрузив, попользоваться второй. Чего тут странного? Я считаю, что когда я командую - проваливай через CoUninitialize, все что связано с COM в моем приложении должно почиститься. Потому что вся инфраструктура должна быть свернута. Если после этой команды я обращусь к какому-нибудь ранее созданному COM интерфейсу я отхвачу excеption, значит COM предполагает, что все что было сделано между ее инициализацией и ее деинициализацией стало невалидным! Это поведение ожидаемо и логично для меня, как для разработчика. Дом разрушается, все жильцы должны быть выселены, и мне плевать, что у кого-то еще не сварился суп или кто-то смотрит телевизор. Возьмем к примеру остановку работу всего процесса. Система же как-то в этот момент останавливат всех и все останавливается. Она взрывает дом вместе с жильцами? Почему я не могу сделать тоже самое в рамках своего потока, внутри процесса ни по-хорошему, ни по-плохому? Как было правильно замечено, у компоненты должен быть специальная команда, которая позволяла бы ей сразу завершить свою работу, но разве CoUninitialize никак не уведомляет ее о том, что все, пора валить? Я полагаю, что это должно работать как с DLL, когда она получает уведомление PROCESS_DETACH. Вот это действительно странно ... |
|||
:
Нравится:
Не нравится:
|
|||
08.01.2019, 12:35 |
|
COM гарантированное освобождение ресурсов
|
|||
---|---|---|---|
#18+
kealon(Ruslan)ну покажет ..., и что он там разберёт без отладочных файлов? Может, и ничего. Но был у меня случай: появлялась странная ошибка Invalid Handle. DrMemory показал, что идёт запись двух байт за пределами выделенной мною области, что и перезаписывало кусок хэндла. В итоге до меня таки дошло, что я ошибся с объявлением структуры и поэтому памяти под неё выделялось на два байта меньше, чем ожидала библиотека. Естественно, отладочных файлов самой библиотеки у меня не было. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
08.01.2019, 13:50 |
|
|
start [/forum/topic.php?fid=57&msg=39756434&tid=2017687]: |
0ms |
get settings: |
8ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
22ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
40ms |
get tp. blocked users: |
1ms |
others: | 12ms |
total: | 110ms |
0 / 0 |