Показать сообщение отдельно
Старый 20.01.2023, 14:10   #1  
online
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,875 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Post Сборка мусора, освобождение файлов (TextIo) и блокировки.
Всем привет.

Похоже я обнаружил интересный плавающий баг ядра по работе с файлами в аксапте.
Принято считать что при вызове метода finalize() или при обнулении ссылки (а точнее всех ссылок) на файловую переменную в аксапте, ядро закрывает файл и высвобождает все ресурсы.
Finalize & null

Как бы не так. Выявился сценарий, при котором этого не происходит. Что еще хуже - высвобождение происходит, но с некоторой случайностью, может высвободиться сразу, может спустя несколько минут, а может и не высвободиться (но это редко, дольше 6 минут мы не ждали). Хотя в большинстве случаев все высвобождается нормально.

Дано:
Ax2012 R3 или ax4.0 (последний билд)
Сервер аоса win 2016 server version 1607 (OS Build 14393.5427)


Работает пакетная обработка (тестировали как в IL, так и в p-code)
1. Собирает информацию в аксапте.
2. Формирует в темп папке csv файл при помощи класса TextIo
3. Закрывает файл TextIo (finalize + обнуление файловой переменной, хотя после finalize она и так null)
4. Пакует csv файл в zip архив вызовом 7zip архиватора
5. Удаляет csv файл.
6. Кладет zip архив в базу аксапты.

Таких пакетов 35 штук.
Одновременно могут запускаться примерно до 10.

Обнаружилась проблема: случайным образом архиватор при упаковке не может получить доступа csv файлу и поэтому создает пустой архив размером 22 байта.
Как лечили
а. Поставили в коде проверку (между пп 3 и 4) на размер архива, если слишком маленький, то удаляем его, ждем 5 секунд и все по новой. И так до 72 раз (6 минут). Конечно прикрутили запись логов, из которых видно, что иногда с первой попытки все успешно, иногда с 10-й, иногда с 35 а иногда и 72 не хватает. Тогда пакетная обработка вываливается в ошибку. В большинстве случаев все нормально.
Получается, что в большинстве случаев файл отпускается сразу, но иногда спустя некоторое время. Иногда это время очень большое, так что мы не дожидались.

При этом пока идут эти 72 разрешенные попытки, есть 6 минут посмотреть самим что там проиcходит. Тотал коммандер просмотрщиком csv файл на чтение открывает. Копировать тоже позволяет. Архиватор заархивировать не может. Пишет примерно так:
Цитата:
c:\Program Files\Microsoft Dynamics AX\60\Server\YYY\bin>7za.exe a C:\Users\XXXX\AppData\Local\Temp\test-1.zip c:\Users\XXXX\AppData\Local\Temp\Article_2023-01-15_16-51-15.csv

7-Zip (a) [32] 16.04 : Copyright (c) 1999-2016 Igor Pavlov : 2016-10-04

Scanning the drive:
1 file, 12826 bytes (13 KiB)

Creating archive: C:\Users\XXXX\AppData\Local\Temp\test-1.zip

Items to compress: 1


WARNING: The process cannot access the file because it is being used by another process.
c:\Users\XXXX\AppData\Local\Temp\Article_2023-01-15_16-51-15.csv


Files read from disk: 1
Archive size: 22 bytes (1 KiB)

WARNINGS for files:

c:\Users\XXXX\AppData\Local\Temp\Article_2023-01-15_16-51-15.csv : The process cannot access the file because it is being used by another process.
----------------
WARNING: Cannot open 1 file
Я подумал, может есть проблема с архиватором и ему нужны какие-то эксклюзивные права на файл или он его открывает как-то не так как Total Commander (другие WinApi функции винды использует).
Попробовал WinRar
Та же проблема. Не может получить доступ к файлу.
Запускал так
Цитата:
c:\Program Files\Microsoft Dynamics AX\60\Server\YYY\bin>"c:\Program Files\WinRAR\WinRAR.exe" a -afzip -ep1 "c:\Users\XXXX\AppData\Local\Temp\Sorting_2023-01-15_18-41-46.csv_rar_ep1.zip" "c:\Users\XXXX\AppData\Local\Temp\Sorting_2023-01-15_18-41-46.csv"
Попробовал из под аоса аксапты через .Net библиотеку создавать архив - тоже выдает ошибку.
Делал через System.IO.Compression.ZipFile
как описано тут
https://community.dynamics.com/ax/f/...les-in-ax-2012

в общем, проблема, похоже, не в архиваторах.


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

Антивируса, который мог бы блокировать в момент проверок, не было, отключили.

В итоге заменили все вызовы TextIo на System.IO.StreamWriter
Очистку ресурсов делаем как
streamWriter.Close();
streamWriter.Dispose();
streamWriter = null;

все заработало. Архиватор всегда пакует все с одной попытки. За 2 суток ни одной проблемы.
За это сообщение автора поблагодарили: Ace of Database (3), _scorp_ (5), Товарищ ♂uatr (4), alex55 (1).