Дело об ошибке сжатия файлов

На днях Брайс пытался упаковать последнюю версию исходного кода программы Process Monitor с тем, чтобы отправить ее мне. Для этого он решил обратиться к функции проводника, именуемой Send To Compressed (zipped) Folder (Отправить в сжатую ZIP-папку) (см. иллюстрацию).

clip_image001

Но не тут-то было - вместо того, чтобы вывести индикатор выполнения и предоставить возможность изменить имя конечного сжатого файла, проводник прервал процесс сжатия со следующей ошибкой:

clip_image002

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

В этот момент я зашел к нему в кабинет, и он показал мне, что происходит. После нескольких неудачных попыток в недоумении уже пребывали мы оба. Нужно было начинать расследование.

 

Мы запустили программу Process Monitor, воспроизвели сбой, остановили сбор данных и изучили тысячи операций в трассировке, разыскивая ошибки. В начале журнала обнаружилась масса ошибок NOT FOUND (НЕ НАЙДЕНО), которые в обычных условиях свидетельствуют о проводимой приложением проверке на предмет существования файла и потому совершенно безобидны. Правда, в данном случае их было необычно много, и все они были связаны с проверкой существования архива, в который предполагалось поместить выделенные файлы.

clip_image001[4]

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

Через несколько сотен событий мы натолкнулись на ошибку SHARING VIOLATION (НАРУШЕНИЕ ОБЩЕГО ДОСТУПА), которую стоило расследовать сразу.

clip_image002[4]

Когда процесс открывает файл, он может указать, нужно ли, и если да, то как нужно организовать общий доступ к этому файлу для других процессов в то время, когда он будет находиться в открытом состоянии. Существует три вида общего доступа: на чтение, на запись и на удаление. Каждому из них соответствует определенный флаг, который процесс передает API-интерфейсу CreateFile. В операции, завершившейся ошибкой, проводник не передавал ни один из этих флагов. Это значит, что намерения организовывать общий доступ к файлу не было, что и подтверждается значением в поле ShareMode.

clip_image003

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

Возвращаясь к трассировке, отметим, что непосредственно перед попыткой открытия файла, завершившейся ошибкой, его открыл процесс с именем Inort.exe. Операции закрытия этого файла процессом Inort на снимке экрана не видно, поскольку оно имеет место значительно позже ошибки проводника при попытке его открытия. Таким образом, нежелание проводника делить доступ к файлу с третьей стороной в сочетании с открытием файла процессом Inort привело к конфликту, и это несмотря на то, что Inort при открытии разрешил общий доступ на чтение, запись и удаление.

В итоге с помощью программы Process Monitor нам удалось раскрыть очередное дело. Очевидно, что нарушение общего доступа было связано с попыткой проводника открыть файл, ранее открытый процессом Inort. Вероятнее всего, с этим же связано и малоинформативное сообщение об ошибке. Далее нам нужно было выяснить, что собой представляет процесс Inort, чтобы придумать способ устранения проблемы или обходной путь. На этот вопрос мы ответили благодаря всплывающей подсказке с характеристиками образа в программе Process Monitor.

clip_image004

eTrust, антивирусная программа компании Computer Associates, очевидно, открыла файл для сканирования на предмет вирусов, чем и помешала проводнику. Работа антивируса должна быть незаметна для системы, а значит, разработчиками eTrust была допущена погрешность. В итоге, чтобы предотвратить появление ошибки в дальнейшем, Брайсу пришлось настроить фильтр, запрещающий сканирование каталогов с исходным кодом в режиме реального времени. 

Когда я вернулся в своей кабинет, мне не удалось воспроизвести эту ошибку. Возможно, подумал я, в моей системе установлена другая версия Inoculan. Судя по данным на страницах свойств процессов в диалоговом окне свойств события программы Process Monitor, у Брайса стояла версия 7.01.0192.0001 антивирусной программы, а у меня - более свежая версия 7.01.0501.000.

clip_image005clip_image006

Почему у нас стояли разные версии, не совсем понятно, поскольку мы оба устанавливали их из образов, которые централизованно координируются ИТ-отделом корпорации Майкрософт. Как бы то ни было, похоже, специалисты компании Computer Associates в какой-то момент заметили и исправили ошибку.

Теперь настало время вернуться к проблеме неэффективного алгоритма сжатия, реализованного в проводнике. С помощью программы Process Monitor я выполнил трассировку сжатия одного файла и посчитал связанные с этой задачей операции. Даже в таком простом случае проводник умудрился открыть конечный ZIP-файл 14 раз, причем 12 из них - до того, как этот файл был фактически создан (а значит, попытки обращения к нему завершались ошибкой NOT FOUND). Операция же поиска конечного файла в каталоге была произведена целых 19 раз! Аналогичная ситуация складывалась с исходным файлом. Он открывался 28 раз, а его основные свойства запрашивались 17 раз. Ну то есть не сказать, что проводник не дает программе eTrust никаких возможностей создать конфликты, связанные с общим доступом.

Желая убедиться, что в неэффективности операций, связанных со сжатием, виноват именно проводник, а не какое-нибудь расширение стороннего производителя, я исследовал стеки различных событий, каждый раз выделяя событие и нажатием сочетания клавиш CTRL+K открывая диалоговое окно его свойств на странице стека.

clip_image007

В большинстве трассировок фигурировала библиотека сжатия файлов проводника Zipfldr.dll, а значит, увы, проблема именно в механизме сжатия. Кстати говоря, с увеличением числа файлов, подлежащих сжатию, число избыточных операций увеличивается в геометрической прогрессии. Поскольку существуют сравнительно простые способы усовершенствования этого алгоритма, у нас есть основания надеяться, что в ОС Windows 7 мы получим более эффективный механизм сжатия.

Обновление! Мне стало известно, что при подготовке пакета обновления 1 (SP1) для ОС Windows Vista механизм сжатия был доработан, и теперь он выполняет меньше операций с файлами.

Под конец - новости для желающих послушать мое «живое» выступление. Приходите на конференцию Wintellect Devscovery, которая состоится Редмонде 14-16 августа - я буду вещать об изменениях в ядре ОС Windows Vista.