【问题标题】:unlink() fails with "No such file or directory" right after existence was checkedunlink() 在检查存在后立即失败并显示“没有这样的文件或目录”
【发布时间】:2016-10-17 19:54:12
【问题描述】:

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

我有以下功能:

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() 有时会失败?

【问题讨论】:

    标签: c++ linux file filesystems


    【解决方案1】:

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

    因为通话不会同时发生。

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

    在软件开发中,检查时间到使用时间(TOCTTOU 或 TOCTOU,发音为“TOCK too”)是一类软件错误,由 在检查条件(例如 安全凭证)以及该检查结果的使用。这是 竞争条件的一个示例。

    【讨论】:

    • 事实并非如此。没有竞争条件,因为只有一个实体可以访问存储。
    • @peku33 只有一个实体可以访问存储显然没有。 这个错误有一个名字和一个维基百科页面。并且在删除之前检查文件是否存在一个竞争条件,它不仅没有用,而且不完整。那么如果仅仅存在呢。它是只读文件系统吗?进程是否有删除权限?除非您重新创建所有已完成的检查由于您无权访问内核而没有数据可做,否则它是无用的。
    【解决方案2】:

    这些调用的强度如何?您是否要一次删除数千个文件?还是每秒/分钟一两个?通过网络,您可能会遇到各种超时,这些超时可能被解释为“没有这样的文件或目录”,但实际上是另一个问题。

    如果你还是要删除它们,为什么还要检查它们的存在呢?只需删除它们,并检查异常以了解它是否不存在,或者是否存在其他错误 - 甚至不这样做。要么它们消失了,要么你无论如何都不能删除它们......

    【讨论】:

    • 每分钟调用一次 cleanup() 循环会删除 10 个文件。计算机和存储在 1Gbps 局域网上。该程序是存储设备的唯一用户。如果我得到“没有这样的文件...” - 该文件是否真的被删除了?
    • "文件是否真的被删除了?"通常,是的。但是,如果文件对您隐藏,就您而言,它不存在 - 即使它可能仍然存在。这完全取决于您的权限。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-13
    • 2021-05-13
    • 1970-01-01
    相关资源
    最近更新 更多