unlink()失败,"没有这样的文件或目录"在检查后存在

时间:2016-06-16 10:38:59

标签: c++ linux file filesystems

我在我的应用程序中观察到非常奇怪的行为。

我有以下功能:

bool File::Exists(const std::string & Path)
{
    struct stat S;
    if(stat(Path.c_str(), &S) != 0)
        return false;

    if(!S_ISREG(S.st_mode))
        return false;

    return true;
}

void File::Remove(const std::string & Path)
{
    if(unlink(Path.c_str()) != 0)
        throw Exceptions::Exception(EXCEPTION_PARAMS, errno);
}

我使用的代码是:

...
const std::string Path = ...;
if(File::Exists(Path))
    File::Remove(Path);
...

此时抛出异常:

No such file or directory (2)

关键事实:

  • 每1k-10k次呼叫发生一次
  • 要删除的所有文件都是二进制文件,大约20MB
  • 这是在应用程序线程中调用的,但是这是访问这些文件的唯一线程(没有其他线程/进程访问它们)。甚至没有其他进程/用户访问分区。
  • 要删除的文件位于已安装的CIFS(SMB)(网络)安装点

为什么stat()报告文件存在,但unlink()有时会失败?

2 个答案:

答案 0 :(得分:1)

这些电话的密集程度如何?您是否尝试一次删除数千个文件?或者一两秒一分钟?通过网络,您可以获得各种超时,可以解释为"没有这样的文件或目录",但实际上是另一个问题。

如果您还要删除它们,为什么还要费心去检查它们的存在?只需删除它们,并检查异常以查明它是否存在,或者是否存在不同的错误 - 或者甚至不这样做。他们要么已经离开了,要么你无法删除它们......

答案 1 :(得分:1)

为什么stat()报告文件存在,但unlink()有时会失败?

因为呼叫不会同时发生。

这个bug很常见,它有自己的name and even a Wikipedia page

  

在软件开发中,检查时间到使用时间(TOCTTOU或   TOCTOU,发音为“TOCK too”)是由一类软件引起的   在检查条件(例如a)之间的系统变化   安全凭证)和使用该检查的结果。这是   一个竞争条件的例子。