OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Пятница, 03 Декабрь, 2021 16:16

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




Начать новую тему Ответить на тему  [ Сообщений: 4 ] 
Автор Сообщение
 Заголовок сообщения: Кажется, ошибка в TextModels
СообщениеДобавлено: Суббота, 23 Октябрь, 2021 21:50 
Аватара пользователя

Зарегистрирован: Суббота, 16 Февраль, 2008 02:47
Сообщения: 518
Коллеги,

у меня завелась ошибка: иногда после закрытия документа и повторного открытия (в рамках одного запуска ББ) сохраненные изменения пропадали. Т.е. открываешь, изменяешь, закрываешь, открываешь - бац! изменения пропали. При этом в файле - измененный документ (видно через odcread). Немало времени и ядреных слов я потратил на восстановление пропащих авторских правок.
В чем же дело?
ББ гарантирует, что одному файлу соответствует один и тот же Files.File; зная это, я предполагал, что где-то в системе нет-нет, да и притаится паразитный указатель на файл, который не ликвидируется после закрытия окна с документом. У меня в ББ много "примочек" к редактору, которые кэшируют читателей TextModels.Reader (а внутри них есть иногда указатель на файл, из которого прочитан текст) и сканеры TextMappers.Scanner (а внутри них есть читатель). Я перерыл свои модули, перепроверил кэши, все аккуратно очистил - безрезультатно.

Кажется, ошибка была в TextModels. Процедура PROCEDURE (text: TextModels.Model) NewReader (rd: TextModels.Reader) позволяет, для экономии памяти, передать rd, который будет переиспользован - т.е. можно взять чтеца, попользоваться, потом переподключить его к другому тексту и пользоваться дальше. Это описано в документации и немало используется в ББ. И вот я выяснил, что при переподключении важное поле Reader.run не переинициализируется. Это видно из анализа процедур TextModels.StdModel.NewReader и TextModels.StdReader.SetPos. А именно Reader.run после чтения текста из файла содержит указатель на TextModels.Piece, который содержит указатель на Files.File - это как раз и получается "фантомная" файловая переменная, которая незримо "висит" и не дает ББ видеть обновленную версию файла.

Вот проверочный модуль. Он пишет в журнал имя "зацепленного" файла, а также показывает стек вызовов, в котором можно также убедиться в сохранении лишнего указателя.
Код:
MODULE BugReaders;

   IMPORT SYSTEM, TextModels, Views, Models, Files, Services, Log;
   
   TYPE
      Reader = POINTER TO RECORD
         eot*: BOOLEAN;
         attr*: INTEGER;
         char*: CHAR;
         view*: Views.View;
         w*, h*: INTEGER;
         base: INTEGER;   (* base = Base() *)
         pos: INTEGER;   (* pos = Pos() *)
         era: INTEGER;
         run: ANYPTR;   (* era = base.era => Pos(run) + off = pos *)
         off: INTEGER;   (* era = base.era => 0 <= off < run.len *)
         reader: Files.Reader   (* file reader cache *)
      END;
      
      Piece = POINTER TO RECORD
         prev, next, len, attr: INTEGER;
         file: Files.File
      END;
      
      File = POINTER TO RECORD
         type-: Files.Type;
         init: BOOLEAN;
         state: INTEGER;
         name: ARRAY 256 OF CHAR;
      END;
   
   PROCEDURE Hack (rd: TextModels.Reader);
      VAR nm: ARRAY 64 OF CHAR; rdr: Reader; pc: Piece; f: File;
   BEGIN
      Services.GetTypeName(rd, nm);
      IF nm # "TextModels.StdReader" THEN Log.String("~(rd IS TextModels.StdReader"); Log.Ln
      ELSE
         rdr := SYSTEM.VAL(Reader, rd);
         IF rdr.run = NIL THEN Log.String(".run = NIL"); Log.Ln
         ELSE
            Services.GetTypeName(rdr.run, nm);
            IF nm # "TextModels.Piece" THEN Log.String("~(rd.run IS TextModels.Piece"); Log.Ln
            ELSE
               pc := SYSTEM.VAL(Piece, rdr.run);
               IF pc.file = NIL THEN Log.String("rd.run.file = NIL"); Log.Ln
               ELSE
                  f := SYSTEM.VAL(File, pc.file);
                  Log.String("rd.run.file.name = "); Log.String(f.name); Log.Ln
               END
            END
         END
      END
   END Hack;
      
   
   PROCEDURE Do*;
      VAR rd: TextModels.Reader; t: Models.Model; v: Views.View;
   BEGIN
      v := Views.OldView(Files.dir.This('System/Rsrc/'), 'Menus.odc');
      t := v.ThisModel();
      WITH t: TextModels.Model DO
         rd := TextModels.dir.New().NewReader(rd);
         Hack(rd);
         rd := t.NewReader(NIL); rd.Read;
         Hack(rd);
         rd := TextModels.dir.New().NewReader(rd);
         Hack(rd);
         HALT(0)
      END
   END Do;

END BugReaders.
(!) BugReaders.Do

После BugReaders.Do в журнале - дважды имя файла System/Rsrc/Menus.odc, хотя должно быть лишь один.

А вот поправка в TextModels.StdModel.NewReader, которая, кажется, должна и исправляет ошибку:
Код:
   PROCEDURE (t: StdModel) NewReader (old: Reader): Reader;
      VAR rd: StdReader;
   BEGIN
      StdInit(t);
      IF (old # NIL) & (old IS StdReader) THEN rd := old(StdReader) ELSE NEW(rd) END;
      IF rd.base # t THEN
         rd.base := t; rd.era := -1; (*==>*) rd.run := NIL; (*<==*) rd.SetPos(0)
      ELSIF rd.pos > t.len THEN
         rd.SetPos(t.len)
      END;
      rd.eot := FALSE;
      RETURN rd
   END NewReader;


С этой поправкой BugReaders.Do, как и ожидается, выдает имя файла System/Rsrc/Menus.odc только один раз. И у меня вроде пропали фантомные файлы.

Что скажете? Прошу поразмыслить, попробовать, и в конечном итоге - предлагаю включить поправку в ББ.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Кажется, ошибка в TextModels
СообщениеДобавлено: Воскресенье, 24 Октябрь, 2021 01:58 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9447
Откуда: Россия, Орёл
Хм, на Wine периодически сталкиваемся с ошибкой, что нельзя сохранить документ (не удаётся записать файл). При повторном Ctrl-S, как правило, норм.
Похоже, это ноги оттуда же растут.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Кажется, ошибка в TextModels
СообщениеДобавлено: Воскресенье, 24 Октябрь, 2021 07:55 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3168
Аргументы выглядят убедительно.

Вот тут ещё есть некий буфер, судя по комментарию, который вероятно также лучше очищать во избежание проблем?
Вложение:
reader.png
reader.png [ 18.2 КБ | Просмотров: 450 ]


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Кажется, ошибка в TextModels
СообщениеДобавлено: Воскресенье, 24 Октябрь, 2021 11:41 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4558
Откуда: Россия, Орёл
Илья Ермаков писал(а):
Хм, на Wine периодически сталкиваемся с ошибкой, что нельзя сохранить документ (не удаётся записать файл). При повторном Ctrl-S, как правило, норм.
Похоже, это ноги оттуда же растут.

Нет, это связано, на сколько я помню, с особенностями работы самого Wine.


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

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


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

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


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

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