Reputation: 2579
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;
}
}
Upvotes: 4
Views: 5801
Reputation: 1464
As of Aug./Sept. 2020 this issue also appeared for RStdio 1.2.5033 and 1.3.1073 - created an issue with RStudio dev on gihtub.
They expect their next boost update to fix this bug (again).
Putting this here although it is an RStudio topic - in case someone runs into this from the RStudio side.
Upvotes: 1
Reputation: 194
I was hitting this problem in a multi-process situation, so the lock solution by @RED SOFT ADAIR would not help. Until the Boost fix is released, I implemented this:
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());
This worked out fine through the tests I created to expose this problem. lexically_normal
operates on the path string, so it does not care about existence of the path. But it's prone to misinterpretations, when links are involved inside the path.
Upvotes: 1
Reputation: 12238
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.
Upvotes: 2