boost :: filesystem :: relative()无法访问该文件,因为它正由另一个进程使用

时间:2017-06-06 14:49:22

标签: c++ windows c++11 windows-7-x64 boost-filesystem

访问某些网络驱动器时,函数relative(path, base_path)canonical(path, base_path)会引发异常。消息总是:

  

该进程无法访问该文件,因为该文件正由另一个进程

使用

我仅在某些由我们的IT部门运营并包含符号链接的共享网络驱动器上观察到此行为。我无法在本地驱动器或相邻计算机的共享驱动器上引发相同的问题。我们怀疑网络驱动器上使用的存档/备份解决方案也是此处的驱动程序。目前已知的因素是:

  • 驱动器必须是网络共享(驱动器等)
  • 路径需要包含符号链接组件
  • 驱动器在备份/归档解决方案下运行

我的问题是

  • 这是boost::filesystem中的潜在错误吗?
  • 我有什么潜在的boost::filesystem技巧可以解决这个问题吗?

一种可能的解决方法是重新实现relative()函数以仅使用路径操作而不访问文件系统。但我想避免重新实施。

如果测试路径存在问题,可能会出现问题的小型示例程序:

#include <vector>
#include <string>
#include <tuple>
#include <boost/filesystem.hpp>
#include <boost/system/error_code.hpp>

using namespace std;
using namespace boost::filesystem;
using boost::system::error_code;


int main()
{
    vector<string> testpaths = {
        "< path to a directory which is to test >",
    };

    for(auto & line : testpaths)
    {
        if(line.empty()) continue;   // skip empty lines

        cout << " path: " << line << "   ";

        path testpath(line.c_str());
        // simplified testing, use parent of parent
        path basepath = testpath.parent_path().parent_path();

        boost::system::error_code ec;
        path relpath = relative(testpath, basepath, ec);
        if(ec)  cout << "  ---> error: " << ec.message();
        else    cout << " ok, relative: " << relpath.string();
        cout << endl;
    }
}

3 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,其中路径仅包含使用boost 1.65.1的目录:

unexpected exception: boost::filesystem::weakly_canonical: The process cannot access the file because it is being used by another process; 

这也仅在路径包含符号链接时在网络驱动器上发生。

这似乎是一个同步问题。显然,使用boost:filesystem不能并行访问相同的符号链接。 我定义了一个自定义函数,该函数封装并同步对weakly_canonical的访问:

static boost::recursive_mutex   sgCanonicalMutex;

boost::filesystem::path CanonicalPath(const boost::filesystem::path inPath)
{        
        boost::recursive_mutex::scoped_lock lk(sgCanonicalMutex);
        return boost::filesystem::weakly_canonical(inPath);
}

在进行此更改后,此问题不再发生。 在boost :: filesystem :: status的文档中也有关于底层系统错误代码ERROR_SHARING_VIOLATION的注释。参见https://www.boost.org/doc/libs/1_70_0/libs/filesystem/doc/reference.html

我认为根本原因在于推动力来源:    boost \ libs \ filesystem \ src \ operations.cpp

read_symlink函数包含

handle_wrapper h(
      create_file_handle(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0));

第三个参数(值0)是传递给CreateFileW的dwShareMode(请参见https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew)。 此参数可能应为FILE_SHARE_READ。最新升幅1.70仍未改变。

答案 1 :(得分:1)

我在多进程情况下遇到了此问题,因此@RED SOFT ADAIR的锁定解决方案无济于事。在发布Boost修复之前,我已经实现了这一点:

auto full_path = boost::filesystem::path(path_str).lexically_normal();
MY_ASSERT(boost::filesystem::exists(full_path), "Path normalization of '%s' resulted in non-existing path '%s'", 
            path_str.c_str(), full_path.string().c_str());

通过我创建的暴露此问题的测试,这可以很好地解决。 lexically_normal对路径字符串进行操作,因此它并不关心路径的存在。但是,当路径中包含链接时,很容易产生误解。

答案 2 :(得分:1)

截至8月/ 9月2020年,RStdio 1.2.5033和1.3.1073-created an issue with RStudio dev on gihtub也出现了此问题。 他们希望他们的下一个增强更新可以再次修复此错误。
尽管这是RStudio主题,但还是放在这里-以防有人从RStudio端碰到它。