当 CreateDirectory 返回 ERROR_ACCESS_DENIED 且“不应该”时

发布于 2024-09-15 04:53:29 字数 801 浏览 0 评论 0原文

我的 Win32 应用程序 A1(实际上是进程的集合)正在尝试使用 CreateDirectory 在父目录 P 中创建目录 D1。P 的路径是 TMP 的值环境变量,这使得 P 成为一个潜在繁忙但通常宽松的地方。绝大多数情况下,一切都工作正常,但很少有 CreateDirectory 失败,GetLastError 然后返回 ERROR_ACCESS_DENIED,其含义在此上下文没有记录。

我编写了一个测试应用程序 A2,它除了在 P 内尽可能快地重复创建和删除目录 D2 之外什么也不做,并且我为 D2 选择了一个愚蠢的长名称,我相信它不会与任何其他程序使用的任何名称发生冲突。每隔几分钟,就会有一小部分时间,在此期间 A2 尝试创建 D2 仅产生 ERROR_ACCESS_DENIED 失败。

A1 在运行期间在 P 内变得非常忙碌。当 A1 和 A2 并发运行时,ERROR_ACCESS_DENIED 故障发生的频率会更高一些,就好像 A1 和 A2 正在竞争对 P 的独占访问权一样。(我绝对确定 A1 不会使用相同的访问权限)名称为 D2。:-)

我有点倾向于将 ERROR_ACCESS_DENIED 理解为“在几毫秒内重试,如果几次尝试后不起作用,则放弃”,但我我担心 [a] 在某些情况下,这可能意味着一些永久性的事情,我应该立即注意,并且 [b] 因为我真的不知道发生了什么,所以可能无法自信地确定合理的时间来处理继续努力。

有人有这方面的经验吗?有什么建议吗?此时特别有价值的是有关导致此问题的原因的线索,以便我可以更轻松地重现问题。

My Win32 app A1 (actually a collection of processes) is trying to use CreateDirectory to create a directory D1 within parent directory P. The path to P is the value of the TMP environment variable, which makes P a potentially busy but generally permissive place. The vast majority of the time, everything works fine, but, rarely, CreateDirectory fails and GetLastError then returns ERROR_ACCESS_DENIED, the meaning of which in this context is not documented.

I wrote a test application A2 which does nothing but repeatedly create and delete a directory D2 as fast as it can within P, and I chose a goofy long name for D2 which I'm confident does not collide with any that any other program would use. Once every few minutes, there's a small fraction of a second during which A2's attempts to create D2 yield only ERROR_ACCESS_DENIED failures.

A1 gets quite busy within P during its run. While A1 and A2 are running concurrently, the periods of ERROR_ACCESS_DENIED failure occur somewhat more frequently, as if A1 and A2 are competing for exclusive access to P. (I am absolutely certain that A1 does not use the same name as D2. :-)

I'm somewhat inclined to take ERROR_ACCESS_DENIED to mean "try again in a few milliseconds, and if that doesn't work after a few tries, give up", but I'm concerned that [a] in some cases it may mean something permanent that I should heed right away, and [b] because I don't really know what's happening, it may not be possible to confidently establish a reasonable amount of time to keep trying.

Anybody have experience with this? Any advice? Of particular value at this point would be clues about what causes this so I can reproduce the problem more easily.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

岛徒 2024-09-22 04:53:29

你说得对。 文档甚至没有列出 ERROR_ACCESS_DENIED作为该函数可能的错误代码,因此它很可能是一个错误。

我会按照您的建议实施重试/退避策略。

换句话说,如果您收到该错误,请无延迟地重试最多 3 次(如果您收到非错误返回代码,显然可以在此处的任何点停止),然后最多再尝试 4 次,并延迟(例如, 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

You're dead right. The documentation doesn't even list ERROR_ACCESS_DENIED as a possible error code for that function so it may well be a bug.

I would do as you suggest in implementing a retry/backoff strategy.

In other words, if you get that error, try again up to three times with no delay (obviously stop at any point here if you get a non-error return code), then up to four more times with delays of (for example, 100 milliseconds, 500 milliseconds, 1 second and 2 seconds).

This sort of strategy (which I've used before) usually gets around any temporary resource shortages. If you still can't create the directory after 7 attempts and 3.6+ seconds, you can probably safely assume it's not going to happen.

Your function could be as ugly as (pseudo-code):

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);

but you may want you make it a little more elegant:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文