OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Понедельник, 23 Апрель, 2018 00:53

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 15 ] 
Автор Сообщение
 Заголовок сообщения: Защита от выгрузки реализации
СообщениеДобавлено: Пятница, 14 Февраль, 2014 14:16 

Зарегистрирован: Вторник, 29 Август, 2006 12:32
Сообщения: 2488
Откуда: Россия, Ярославль
В процессе работы столкнулся с данной "проблемой", часто бывает так, что вношу модификации в работающую реализацию. А затем по привычке выгружаю эту реализацию вместе с модулем. И получаю закономерный трэп. Это проблема этапа разработки.
Похожая ситуация происходит при закрытии ББ. Модули реализаций выгружаются и клиентский код уже не может корректно выполнить свои завершающие действия (ведь ему все еще нужна реализация). Такая проблема уже может возникнуть в боевом режиме, и будет очень неприятно.
Решений, как всегда несколько:

    Реализовать корректную обработку выгрузки в клиентском коде. Идеальный случай. В реальности получается перекладывание ответственности на клиента. Приходится часто делать проверку указателя
    Код:
    PROCEDURE Valid(a: ANYPTR): BOOLEAN;
          VAR i: Meta.Item;
       BEGIN
          Meta.GetItem(a, i);
       RETURN i.Valid();
       END Valid;
    Вручную создавать специальный модуль, импортирующий реализации (как HostMenus). Работает только для подконтрольных реализаций, и не спасает от второго случая.
    Реализовать механизм выгрузки, который бы не позволял без подтверждения выгрузить модули, у которых есть объекты, заякоренные в других модулях. В идеальном случае - дожидаться ситуации при выгрузке модулей, при которой на объекты модуля точно нет внешних ссылок. Но возникает ситуация перекрестных ссылок на объекты модулей, тогда непонятно, как выполнять выгрузку.
    Слабые ссылки, которые предполагают отсутствие гарантии получения объекта, и не якорят чужие объекты. Пример реализации слабых ссылок для ББ в ypkSysRef.
    В случае фабрик можно отказаться от передачи указателя вовне, использовать шину сообщений, например, или поиск по метаинформации. То есть, объект фабрики хранится внутри модуля реализации, и передается клиентам по запросу. Проблема может возникнуть при появлении второй реализации с таким же объектом.
    Не усложнять и перезапускать ББ целиком каждый раз.
Такая вот проблема.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Пятница, 14 Февраль, 2014 20:52 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 2078
Откуда: Красноярск
В "инфо", "загруженные модули" указывается сколько у модуля клиентов. Там реализации считаются? Тогда было бы просто пока > 0 — не выгружать...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Пятница, 14 Февраль, 2014 21:10 

Зарегистрирован: Вторник, 29 Август, 2006 12:32
Сообщения: 2488
Откуда: Россия, Ярославль
Нет, клиенты это те, кто напрямую импортируют модуль. Их и так считает ядро.


Последний раз редактировалось Пётр Кушнир Пятница, 14 Февраль, 2014 21:20, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Пятница, 14 Февраль, 2014 21:16 

Зарегистрирован: Вторник, 29 Август, 2006 12:32
Сообщения: 2488
Откуда: Россия, Ярославль
Возможно, как простое решение, будет полезен этакий FactoryRef, статический объект, который бы помогал юзеру устанавливать одну или более скрытую реализацию заданного базового типа (хуки, фабрики, процедурные переменные, в общем, все подряд) и корректно следить за их состоянием, помогать с миграцией от одной реализации к другой в рантайме и т.д.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Пятница, 14 Февраль, 2014 21:40 

Зарегистрирован: Вторник, 29 Август, 2006 12:32
Сообщения: 2488
Откуда: Россия, Ярославль
Код:
   PROCEDURE Exec (a: Action);
      VAR t: Kernel.Type;
   BEGIN
      t := Kernel.TypeOf(a);
      IF t.mod.refcnt >= 0 THEN   (* execute action if its module is not unloaded *)
         a.Do   (* warning: here the actions and candidates lists may be modified, or a trap may occur! *)
      END
   END Exec;

Вот как справляются с похожей проблемой в Services.
То есть, для типов, которые могут иметь скрытые расширения, можно и нужно выполнять проверку указателей на валидность.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Пятница, 14 Февраль, 2014 22:13 

Зарегистрирован: Вторник, 29 Август, 2006 12:32
Сообщения: 2488
Откуда: Россия, Ярославль
Тут еще от задачи зависит, например, понятно, что я не буду в здравом уме выгружать модуль с фабрикой реализации окон прямо в работающей системе.
С другой стороны, очень удобно писать новый модуль окон и выгружать его в процессе написания. И лучше бы, чтобы трэпов не было, пусть даже они не мешают.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Суббота, 15 Февраль, 2014 00:36 

Зарегистрирован: Вторник, 29 Август, 2006 12:32
Сообщения: 2488
Откуда: Россия, Ярославль
Проблема осознанной деинсталляции хука возникает еще и потому что обычно указатель на хук передается на хранение вовне без знания того, кому он передается, поэтому, даже внутри финализатора не всегда можно определить, откуда этот хук должен быть деинсталлирован, если такая возможность вообще существует. Поэтому реализация финализатора не обеспечит бескровную возможность выгрузить модуль.
Иными словами, объект не может сам сообщить о невалидности своему владельцу.

Получается, что для проверки валидности всегда нужен промежуточный объект (возможно хранимый в объектном пуле, для эффективности).
Для критичных мест получается что-то типа:
Код:
MODULE Abase;

   TYPE
      A* = POINTER TO ABSTRACT RECORD END;
      
      (* всегда рядом с абстракцией, то есть, не выгрузится пока есть клиенты *)
      SafeA = POINTER TO RECORD (A0)
         unsafe: A;
      END;
      
   PROCEDURE (a: A) Do*, NEW, ABSTRACT;
   
   PROCEDURE (a: SafeA) Do;
   BEGIN
      IF Valid(a.unsafe) THEN a.Do END
   END Do;
   
   PROCEDURE New*(): A;
      VAR a: SafeA;
   BEGIN
      NEW(a);
      a.unsafe:=dir.New();
      RETURN a
   END New;

END Abase.

Сработает ли финализатор объекта из модуля реализаций, который заякорен в базовом модуле? По идее - должен.
Код:
MODULE Aimpl;
   
   TYPE
      HostA = POINTER TO RECORD (Abase.A)
         host: WinApi.A;
      END;
   
   PROCEDURE (a: HostA) Do;
   BEGIN
      (* smth *)
   END Do;
   
   PROCEDURE (a: HostA) FINALIZE;
   BEGIN
      Free(a.host)
   END FINALIZE;
   
END Aimpl.

Для менее критичных случаев подойдет
Код:
    TYPE   
      Ref* = RECORD
         target: ANYPTR;
      END;
      
   PROCEDURE (VAR r: Ref) Set*(x: ANYPTR), NEW;
   BEGIN
      r.target:=x;
   END Set;
   
   PROCEDURE (VAR r: Ref) This*(): ANYPTR, NEW;
      VAR ret: ANYPTR;
   BEGIN
      IF r.target#NIL THEN
         IF Valid(r.target) THEN ret:=r.target ELSE r.target:=NIL END;
      END;
      RETURN ret
   END This;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Понедельник, 16 Июнь, 2014 23:05 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2929
Откуда: г. Ярославль
Вот как раз столкнулся с этой проблемой. Суть в том, что объекты HostFonts связаны с объектами шрифтов, порождёнными библиотекой SDL_TTF. Следовательно, надо их корректно уничтожать средствами SDL_TTF при зачистке HostFonts.Font (в методе FINALZE). Но средства SDL_TTF загружены компонентно - в виде модуля, реализующего хук для некоего абстрактного интерфейса.

И получается так, что при закрытии BlackBox сперва выгружается хук, а потом начинают зачищаться объекты HostFonts - а они уже не могут обратиться к функциональности хука!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Вторник, 17 Июнь, 2014 12:17 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2929
Откуда: г. Ярославль
Провёл тут лабораторную работу.

Написал три модуля:
Код:
MODULE PrivA;
   IMPORT Log, PrivB, PrivC;
   PROCEDURE Do*;
   BEGIN
      Log.String('PrivA.Do'); Log.Ln;
   END Do;
BEGIN
   Log.String('PrivA Init'); Log.Ln;
END PrivA.

MODULE PrivB;
   IMPORT Log;
BEGIN
   Log.String('PrivB Init'); Log.Ln
CLOSE
   HALT(101)
END PrivB.

MODULE PrivC;
   IMPORT Log;
BEGIN
   Log.String('PrivC Init'); Log.Ln;
CLOSE
   HALT(102)
END PrivC.


Если выполнить PrivA.Do, то получим такие записи в журнале:
Цитата:
PrivB Init
PrivC Init
PrivA Init
PrivA.Do
А в списке загруженных модулей увидим последовательность:
Цитата:
PrivA
PrivC
PrivB
Это означает, что сперва загрузился модуль A. После чего пошла загрузка модулей с конца списка импорта модуля А и загрузился сперва модуль C, а потом B. После того, как модули оказались загружены, начинают работу секции BEGIN каждого из них - только уже в том порядке, в каком они импортированы в A.

А выгружаться они будут в том же порядке, что и загружались - A, C, B.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Вторник, 17 Июнь, 2014 17:23 

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 7814
Откуда: Троицк, Москва
Иван Кузьмицкий писал(а):
Это означает, что сперва загрузился модуль A. ...
Означает -- это только гипотеза.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Среда, 18 Июнь, 2014 09:09 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2929
Откуда: г. Ярославль
Info21 писал(а):
Иван Кузьмицкий писал(а):
Это означает, что сперва загрузился модуль A. ...
Означает -- это только гипотеза.
Подозреваю, что последовательности загрузки-выгрузки модулей и, главное, их инициализации не произвольны, но доказать это на данный момент выше моих сил :(


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Среда, 18 Июнь, 2014 11:30 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2289
Откуда: Россия, Санкт-Петербург
Иван Кузьмицкий писал(а):
Подозреваю, что последовательности загрузки-выгрузки модулей и, главное, их инициализации не произвольны, но доказать это на данный момент выше моих сил :(
Конечно, не произвольны, а очень даже фиксированы. Это вам не ASLR какой-нибудь. Другой вопрос в том, что при смене реализации нет гарантий сохранения такого поведения в точности. Поэтому надо либо зафиксировать этот момент в документации и требованиях на реализацию, либо не менять реализацию и задокументировать, что на это есть завязка в ваших компонентах.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Среда, 18 Июнь, 2014 11:46 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2929
Откуда: г. Ярославль
Александр Ильин писал(а):
Другой вопрос в том, что при смене реализации нет гарантий сохранения такого поведения в точности. Поэтому надо либо зафиксировать этот момент в документации и требованиях на реализацию
Вот только сегодня утром прямо в разделе IMPORT прописал, для чего именно эти модули тут импортированы и какая связь с другими. Потому что через полгода уже не вспомнить и не объяснить, а сломать будет очень легко.
Александр Ильин писал(а):
Ещё хорошо бы сделать автоматический тест, проверяющий совместимость вашего компонента с реализацией загрузки-выгрузки.
Хорошая идея, спасибо! Надо поразмыслить.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Среда, 18 Июнь, 2014 15:13 

Зарегистрирован: Вторник, 30 Июнь, 2009 14:58
Сообщения: 1438
По теме: http://oberspace.dyndns.org/index.php/t ... l#msg20137


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Защита от выгрузки реализации
СообщениеДобавлено: Воскресенье, 06 Июль, 2014 13:54 

Зарегистрирован: Вторник, 22 Май, 2007 15:38
Сообщения: 118
Откуда: Питер
Цитата:
Ещё хорошо бы сделать автоматический тест, проверяющий совместимость вашего компонента с реализацией загрузки-выгрузки.


Нужно ли огород городить? Ведь последовательность загрузки-выгрузки всегда можно задать явным импортом, независимо от реализации. Я имею в виду, что, например, модуль PrivB может импортировать модуль PrivC.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 15 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2018, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB