когда CreateDirectory возвращает ERROR_ACCESS_DENIED и "не должен" - PullRequest
2 голосов
/ 21 августа 2010

Мое приложение Win32 A1 (на самом деле набор процессов) пытается использовать CreateDirectory для создания каталога D1 в родительском каталоге P. Путь к P - это значение переменной среды TMP, которая делает P потенциально занятое, но в целом разрешающее место. В подавляющем большинстве случаев все работает нормально, но редко CreateDirectory дает сбой, а GetLastError затем возвращает ERROR_ACCESS_DENIED, значение которого в этом контексте не задокументировано.

Я написал тестовое приложение A2, которое ничего не делает, но многократно создает и удаляет каталог D2 настолько быстро, насколько это возможно в P, и я выбрал глупое длинное имя для D2, которое, я уверен, не сталкивается ни с каким другим Программа будет использовать. Раз в несколько минут, есть небольшая доля секунды, в течение которой попытки А2 создать D2 приводят только к ERROR_ACCESS_DENIED сбоям.

А1 очень занят в P во время своего бега. В то время как A1 и A2 работают одновременно, периоды сбоя ERROR_ACCESS_DENIED происходят несколько чаще, как будто A1 и A2 конкурируют за эксклюзивный доступ к P. (Я абсолютно уверен, что A1 не использует то же имя, что и D2.: -)

Я несколько склонен считать ERROR_ACCESS_DENIED значением «попробуйте снова через несколько миллисекунд, и если это не сработает после нескольких попыток, сдавайтесь», но я обеспокоен тем, что [a] в некоторых в некоторых случаях это может означать что-то постоянное, к чему я должен немедленно прислушаться, и [b] поскольку я действительно не знаю, что происходит, возможно, не удастся с уверенностью установить разумное количество времени, чтобы продолжать попытки.

У кого-нибудь есть опыт с этим? Любой совет? Особую ценность на данный момент представляют подсказки о том, что является причиной этого, чтобы я мог легче воспроизвести проблему.

1 Ответ

1 голос
/ 21 августа 2010

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

Я бы поступил так, как вы предлагаете при реализации стратегии повторных попыток / отката.

Другими словами, если вы получите эту ошибку, повторите попытку до трех раз без задержки (очевидно, остановитесь здесь в любой момент, если вы получите код возврата без ошибок), затем еще до четырех раз с задержками например, 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
...