4

另一个问题中,我们确定是的,CreateDirectory偶尔会因 的未记录GetLastError值而失败ERROR_ACCESS_DENIED,并且处理这种情况的正确方法可能是再试几次。实现这样的算法很容易,但是当你不知道如何重现它时,测试它就不是那么容易了。

我不需要理论来解释为什么会发生这种情况。这可能是Windows中的一个错误,是的。它也可能是设计使然。最终,在这一点上,这并不重要,因为微软发布了这种行为,我必须应对。

我也不需要解释多任务操作系统理论以及 Windows 通常如何实现它。我以写系统软件为生。我了解的很少。

我现在需要的是一种重现故障的可靠方法,这样我就可以为应对的代码编写一个测试用例。这是我到目前为止所尝试的:

  • 我编写了测试程序 P1,它缓慢而反复地列举了准父母的内容。同样,我编写了测试程序 P2,它除了反复尝试删除并在可能的父目录中创建一个目录之外什么都不做。我认为长时间保持枚举打开可能会使问题更有可能。单独运行 P2 会偶尔产生一段时间的故障(大约每隔几分钟,持续大约 10 毫秒)。同时运行 P1 和 P2 似乎不会使故障变得更频繁或更长时间。

  • 我同时运行了两个 P2 实例,这似乎并没有使故障变得更频繁或更长时间。

  • 我修改了 P2 以便它可以创建除目录之外的文件,并且在 P1 的同时运行它似乎不会使故障变得更频繁或更长时间。

  • 我同时运行了 P1 和具有不同参数的多个 P2 实例,这似乎并没有使故障变得更频繁或更长时间。

  • 我编写了测试程序 P3,它将项目移入和移出可能的父级,并与 P2 同时运行 P3,这似乎不会使失败更频繁或更长时间。

还有其他想法吗?

4

2 回答 2

1

我敢打赌,您的枚举/删除/创建会导致句柄出现一些同步问题。如果 CreateDirectory 与 CreateFile 类似(我假设它背后的逻辑是共享的),那么您会看到与 CreateFile 类似的行为:

如果您对因先前调用 DeleteFile 而等待删除的文件调用 CreateFile,则该函数将失败。操作系统会延迟文件删除,直到文件的所有句柄都关闭。GetLastError 返回 ERROR_ACCESS_DENIED。

于 2010-09-01T21:34:39.680 回答
1

让我首先仔细检查我是否理解了这个问题。如果你运行类似下面的代码片段,你希望它最终会失败,对吧?

while (true)
{
    System.IO.Directory.CreateDirectory( ".\\FooDir" );
    System.IO.Directory.Delete( ".\\FooDir" );
}

如果您的应用程序是系统上运行的唯一一个打开该文件的句柄的东西,那么这感觉就像一个错误。因此,了解操作系统版本会有所帮助。

另一方面,如果系统中有其他东西使手柄保持打开一段时间,那么这是否是一个错误就变得更加模糊了。试图盲目地挖掘文件和目录的东西的数量可能会让你感到惊讶。例如,一个天真的索引器可能会走进那个目录,枚举它,寻找要索引的文件等等——如果你和他发生冲突,blammo。一个类似幼稚的防病毒过滤器或其他一些文件系统过滤器也可能在戳它(在这种情况下,它仍然感觉像一个错误)。

我们在操作系统中做了一些小事情来尝试提供类似这些方式的服务来让您摆脱困境。如果您关闭索引器,如果您关闭任何防病毒软件,任何反恶意软件,它会重现吗?我们可以从那里开始,希望我们会发现更新的部分已经修复了它(我知道,该声明中有很多假设)。

另一个相对有趣的琐事是 ERROR_ACCESS_DENIED 是一个 Win32 错误,它映射自系统中的多个底层状态(例如,请参见本文)。因此,如果我们能再深入一点,我们也许能够找出文件系统试图告诉应用程序什么(如果它不仅仅是拒绝访问)。

我们最终可能会讨论你是否可以在野外假设你的应用程序是唯一在你的文件和目录中戳的东西。您可能会猜到那个人会去哪里。

于 2010-08-27T15:51:55.447 回答