When accessing some network drives, the functions relative(path, base_path)
and canonical(path, base_path)
throw an exception. The message is always:
The process cannot access the file because it is being used by another process
I've observed this behavior only on some shared network drives that were operated by our IT department and contain symbolic links. I was not able to provoke the same issue on local drives or on shared drives from an adjacent computer. Our suspicion is that the archive/backup solution used on the network drives is also a driver here. The known factors are these so far:
My questions are:
boost::filesystem
?boost::filesystem
tricks that I've missed that would solve the issue?One possible workaround would be to re-implement the relative()
function to use only path manipulation and does not access the filesystem. But I'd like to avoid the re-implementation.
An small sample program that may exhibit the problem if the tested path has the issue:
#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;
}
}
I had the same problem where the path only contains a directory using boost 1.65.1:
unexpected exception: boost::filesystem::weakly_canonical: The process cannot access the file because it is being used by another process;
This also only happens on a network drive when the path contains a symbolic link.
It seems that this is a synchronization problem. Obviously using boost:filesystem the same symbolic link can not be accessed in parallel. I defined a custom function that encapsulates and synchronizes the access to 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);
}
After that change the problem did not occur anymore. There also is a note about the underlying system error code ERROR_SHARING_VIOLATION in the documentation of boost::filesystem::status. See https://www.boost.org/doc/libs/1_70_0/libs/filesystem/doc/reference.html
I think that the root cause is in the boost sources: boost\libs\filesystem\src\operations.cpp
The function read_symlink contains
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));
The third parameter (value 0) is the dwShareMode passed to CreateFileW (see https://learn.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew). This parameter possibly should be FILE_SHARE_READ. This is still left unchanged in the latest boost 1.70.