ReadFile! = 0, lpNumberOfBytesRead = 0, но смещение не находится в конце файла - PullRequest
0 голосов
/ 07 сентября 2018

Мы пытаемся понять источник следующей ошибки:

У нас есть вызов " ReadFile " (синхронный), который возвращает ненулевое значение (успех), но заполняет параметр lpNumberOfBytesRead до 0. Теоретически это означает, что смещение находится за пределами файла но на практике это не так. GetLastError возвращает ERROR_SUCCESS (0).

Все файлы находятся на общем сетевом диске (Windows Server 2016 + DFS, клиенты Windows 8-10, SMBv3). Файлы используются в режиме совместного использования. Блокировка в файле (lockFileEx) используется для одновременного доступа к файлу (мы просто блокируем первый байт файла перед любым чтением / записью).

Используемый дескриптор не является новым: он не создается локально в функциях, а извлекается из общедоступного «менеджера кеша дескрипторов файлов». Это означает, что он мог быть создан (не использован) несколько раз назад. Однако все, что мы сделали, указывает, что дескриптор действителен в момент вызова: GetLastError возвращает 0, GetFileInformationByHandle возвращает «true» и допустимую структуру.

Ошибка записывается в файл, расположенный на том же файловом сервере, что и проблемные файлы.

Мы провели много регистрации и тестирования по этой проблеме. Вот дополнительные факты, которые мы собрали:

  • Большинство (но не все) проблемных операций чтения происходят в самом конце файла: мы читаем последнюю запись. Тем не менее, чтение по-прежнему в файле GetlastError не возвращает ERROR_HANDLE_EOF. Если программа перезапущена, работает то же чтение с теми же параметрами.
  • Проблема не временная: повторные вызовы дают один и тот же результат, даже если мы позволяем программе зацикливаться бесконечно. Однако перезапуск программы не приводит к немедленному повторному возникновению проблемы.
  • Мы уверены, что смещение, если внутри файла: мы проверяем фактическое местоположение указателя файла после сбоя и сравниваем его с ожидаемым значением, а также размером файла, сообщаемым ОС: все совпадения при нескольких повторных попытках.
  • Проблема обнаруживается только случайным образом: программа не работает так, как ожидалось, и программа не работает. Это происходит 2-4 раза в день в нашем офисе (около 20 человек).
  • Эта проблема возникает не только в нашей сети. мы видели симптомы и записи в журналах в нескольких местах, хотя у нас нет четкого представления об ОС, связанной с этими случаями.

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

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

Редактировать 2 (В целях сохранения ясности я удалил код: новые доказательства дают лучшее объяснение проблемы)

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

ProcMon captured lines

Текстовая версия:

"Time of Day","Process Name","PID","Operation","Path","Result","Detail","Command Line"
"9:43:24.8243833 AM","wacprep.exe","33664","ReadFile","\\office.git.ch\dfs\Data\EURDATA\GIT18\JNLS.DTA","END OF FILE","Offset: 7'091'712, Length: 384, Priority: Normal","O:\WinEUR\wacprep.exe  /company:GIT18"
"9:43:24.8244011 AM","wacprep.exe","33664","QueryStandardInformationFile","\\office.git.ch\dfs\Data\EURDATA\GIT18\JNLS.DTA","SUCCESS","AllocationSize: 7'094'272, EndOfFile: 7'092'864, NumberOfLinks: 1, DeletePending: False, Directory: False","O:\WinEUR\wacprep.exe  /company:GIT18"

(их тысячи, так как приложение находится в бесконечном цикле.)

Как мы понимаем, вызов ReadFile должен быть успешным: смещение находится в пределах границы файла. Тем не менее, это не удается. ProcMon сообщает END OF FILE, хотя я подозреваю, что это только потому, что ReadFile возвратил! = 0 и сообщил, что прочитано 0 байт.

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

"Time of Day","Process Name","PID","Operation","Path","Result","Detail","Command Line"
"9:46:58.6204637 AM","wacprep.exe","33664","ReadFile","\\office.git.ch\dfs\Data\EURDATA\GIT18\JNLS.DTA","END OF FILE","Offset: 7'091'712, Length: 384, Priority: Normal","O:\WinEUR\wacprep.exe  /company:GIT18"
"9:46:58.6204810 AM","wacprep.exe","33664","QueryStandardInformationFile","\\office.git.ch\dfs\Data\EURDATA\GIT18\JNLS.DTA","SUCCESS","AllocationSize: 7'094'272, EndOfFile: 7'092'864, NumberOfLinks: 1, DeletePending: False, Directory: False","O:\WinEUR\wacprep.exe  /company:GIT18"
"9:46:58.7270730 AM","wacprep.exe","33664","ReadFile","\\office.git.ch\dfs\Data\EURDATA\GIT18\JNLS.DTA","SUCCESS","Offset: 7'091'712, Length: 384, Priority: Normal","O:\WinEUR\wacprep.exe  /company:GIT18"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...