Когда GOSTIRECTORY возвращает ERROR_ACCESS_DENEDED и «НЕ ДОЛЖЕН»
-
30-09-2019 - |
Вопрос
Мой приложение Win32 A1 (на самом деле коллекция процессов) пытается использовать CreateDirectory
Чтобы создать каталог D1 в родительском каталоге P. Путь к P - это значение TMP
Переменная окружающей среды, которая делает P потенциально занятым, но вообще допустимым местом. Подавляющее большинство того времени, все работает нормально, но, редко, CreateDirectory
не удается и GetLastError
затем возвращает ERROR_ACCESS_DENIED
, Значение которого в этом контексте не документировано.
Я написал тестовое приложение A2, которое ничего не делает, кроме как многократно создает и удалять каталог D2 как можно быстрее, так как он может в P, и я выбрал хорошее имя D2, которое я уверен, что не сталкивается с любой другой программой Отказ Один раз в несколько минут, есть небольшая доля секунды, в течение которой попытки A2 только для создания урожайности D2 ERROR_ACCESS_DENIED
сбои.
A1 становится довольно занятым внутри P во время прогона. В то время как A1 и A2 работают одновременно, периоды ERROR_ACCESS_DENIED
Сбой происходит несколько чаще, как если бы A1 и A2 конкурируют за исключительный доступ к П. (я абсолютно уверен, что A1 не использует то же имя, что и D2. :-)
Я несколько склоннулся брать ERROR_ACCESS_DENIED
Чтобы означать «Попробуйте еще раз в нескольких миллисекундах, и если это не сработает после нескольких попыток, сдаться», но я обеспокоен тем, что [а] в некоторых случаях это может означать что-то постоянное, что я должен содержать сразу, и [b] потому что я не знаю, что происходит, это может быть невозможно уверенно установить разумное количество времени, чтобы продолжать пытаться.
У кого-нибудь есть опыт с этим? Любой совет? Особого значения на данный момент были бы подсказки о том, что вызывает это, чтобы я мог бы воспроизвести проблему легче.
Решение
Вы мертвы справа. То документация Даже не перечисляет ошибку_accESS_DENED в качестве возможного кода ошибки для этой функции, так что вполне может быть ошибка.
Я бы сделал, как вы предложили в реализации стратегии повторной попытки / Backoff.
Другими словами, если вы получите эту ошибку, попробуйте снова до трех раз без задержки (очевидно, остановитесь в любой точке здесь, если вы получите код возврата без ошибок), то до четырех раз с задержками (например, 100 миллисекунд, 500 миллисекунд, 1 секунды и 2 секунды).
Такая стратегия (которую я использовал раньше) обычно охватывает любые временные нехватки ресурсов. Если вы все еще не можете создать каталог после 7 попыток и 3.6+ Десятки, вы, вероятно, можете смело предположить, что это не произойдет.
Ваша функция может быть такой же уродливой, как (псевдокод):
def createMyDir (dirname):
if createDir (dirName) return true;
if createDir (dirName) return true;
if createDir (dirName) return true;
sleep (100)
if createDir (dirName) return true;
sleep (500)
if createDir (dirName) return true;
sleep (1000)
if createDir (dirName) return true;
sleep (2000)
return createDir (dirName);
Но вы можете захотеть, чтобы вы сделали его немного более элегантным:
def createMyDir (dirname):
delay = pointer to array [0, 0, 0, 100, 500, 1000, 2000, -1]
okay = createDir (dirName)
while not okay and [delay] not -1:
if [delay] not 0:
sleep ([delay])
delay = next delay
okay = createDir (dirName)
return okay