SASGIS - SAS.Планета |
View Issue Details |
|
ID | Project | Category | View Status | Date Submitted | Last Update |
0003029 | SAS.Планета | [All Projects] Баг | public | 19-05-2016 10:10 | 19-05-2016 14:39 |
|
Reporter | zed | |
Assigned To | zed | |
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | |
Platform | | OS | | OS Version | |
Product Version | .Nightly | |
Target Version | 160606 | Fixed in Version | 160606 | |
|
Summary | 0003029: AV при уменьшении числа MaxConnectToServerCount из настроек карты |
Description | Если в настройках карты увеличить число качающих потоков, то всё ОК, но если потом попытаться их уменьшить, то вываливается исключение с попыткой обратиться к нулевому адресу вот тут:
procedure TTileDownloaderSimple.OnConfigChange;
var
VTileDownloaderConfigStatic: ITileDownloaderConfigStatic;
begin
VTileDownloaderConfigStatic := FTileDownloaderConfig.GetStatic; // <- AV
...
в указанной строчке переменная FTileDownloaderConfig оказывается не инициализирована, да и весь Self равен nil. |
Steps To Reproduce | |
Additional Information | Видимо, баг в методе нотифаера TNotifierBase.Notify, т.к. он в локе читает список листнеров, а потом вне лока вызывает их. Но может быть ситуация (и это наш случай), когда первый листнер, который получил сообщение (в нашем случае это TTileDownloaderList), берёт и удаляет объекты остальных листнеров этого же нотифаера (TTileDownloaderSimple). И даже не смотря на то, что удаляемые объекты отписываются от нотификаций, им эти нотификации всё равно прилетают, после уничтожения.
procedure TNotifierBase.Notify(const AMsg: IInterface);
var
idx: Integer;
VList: array of IListener;
begin
FSync.BeginRead;
try
SetLength(VList, FListeners.Count);
for idx := 0 to FListeners.Count - 1 do begin
VList[idx] := IListener(Pointer(FListeners[idx]));
end;
finally
FSync.EndRead;
end;
for idx := 0 to Length(VList) - 1 do begin
VList[idx].Notification(AMsg);
VList[idx] := nil;
end;
VList := nil;
end;
|
Tags | No tags attached. |
Relationships | |
Attached Files | |
|
Issue History |
Date Modified | Username | Field | Change |
19-05-2016 10:10 | zed | New Issue | |
19-05-2016 10:16 | zed | Note Added: 0017218 | |
19-05-2016 10:19 | vdemidov | Note Added: 0017219 | |
19-05-2016 10:21 | vdemidov | Note Added: 0017220 | |
19-05-2016 10:23 | vdemidov | Note Added: 0017221 | |
19-05-2016 10:38 | zed | Note Added: 0017222 | |
19-05-2016 10:55 | vdemidov | Note Added: 0017223 | |
19-05-2016 14:39 | zed | Status | new => resolved |
19-05-2016 14:39 | zed | Fixed in Version | => 160606 |
19-05-2016 14:39 | zed | Resolution | open => fixed |
19-05-2016 14:39 | zed | Assigned To | => zed |
19-05-2016 14:39 | zed | Target Version | => 160606 |
Notes |
|
(0017218)
|
zed
|
19-05-2016 10:16
|
|
Думаю впереть вот такую конструкцию для фикса AV конкретно в TTileDownloaderSimple:
procedure TTileDownloaderSimple.OnConfigChange;
var
VTileDownloaderConfigStatic: ITileDownloaderConfigStatic;
begin
if not Assigned(FTileDownloaderConfig) then begin
{$MESSAGE HINT 'http://www.sasgis.org/mantis/view.php?id=3029'}
Exit;
end;
VTileDownloaderConfigStatic := FTileDownloaderConfig.GetStatic;
...
Или есть лучший вариант? |
|
|
|
Да, есть такая проблема. И я не знаю как ее решить. Переделка TNotifierBase.Notify с запихиванием нотификации под лок, только добавит возможность дедлока. |
|
|
|
> Думаю впереть вот такую конструкцию для фикса AV конкретно в TTileDownloaderSimple
Боюсь это проблему, только сделает чуть-чуть более редкой, но не решит. |
|
|
|
Как вариант убрать из TTileDownloaderSimple слежение за конфигом, а следить за ним на уровень выше и при изменении пере создавать весь массив. |
|
|
(0017222)
|
zed
|
19-05-2016 10:38
|
|
Т.е. в TTileDownloaderList.OnConfigChange выкинуть всю ту логику с копированием, а в TTileDownloaderSimple в качестве параметра передавать ITileDownloaderConfigStatic? Можно попробовать. Главное, чтобы в будущем ни у кого не возникло желания сделать оптимизацию и перенести часть слежения обратно в TTileDownloaderSimple. Придётся писать предупреждение от такого. |
|
|
|
>Т.е. в TTileDownloaderList.OnConfigChange выкинуть всю ту логику с копированием, а в TTileDownloaderSimple в качестве параметра передавать ITileDownloaderConfigStatic?
Ага.
Но вообще, нужно что-то придумывать с листенерами и нотифаерами. Я пытался сделать в листенере метод Disconnect, который вызывать в деструкторе класса, который этот листенер подписывает, но потом понял, что это тоже только маскирует часть ошибок. Пока пришел к тому, что пытаюсь всех подписчиков сделать максимально долгоживущими. |
|