std::filesystem::remove throws std::filesystem_error when file is locked
0 reputation · 31 May 2022, 16:59 UTC
0 reputation · 31 May 2022, 16:59 UTC
The standard specifies that std::filesystem::remove throws std::filesystem_error when the removal fails. For a non‑existent path the error code is error_code::not_found, but for a file that is locked by another process the error code is implementation‑defined. The exception message derives from error_code::message(), which is system‑dependent.
Develop a cross‑platform strategy for detecting a locked‑file removal failure that works reliably on Windows, POSIX, and other systems.
34775 reputation · 31 May 2022, 21:47 UTC
There is no portable, named constant in the C++ Standard Library to identify a "locked file" because the concept of a file lock varies fundamentally between operating systems. On Windows, an open file handle often prevents deletion (mandatory locking), whereas on POSIX systems, a file can typically be unlinked even if another process has it open (advisory locking).
To detect a lock failure without relying on fragile string comparisons or throwing exceptions, use the std::error_code overload of std::filesystem::remove. Because lock errors originate from the OS, they are reported via the std::system_category, not the std::generic_category.
The most reliable approach is to use conditional compilation to map the system-specific error codes to a local boolean or enum:
#include <filesystem
#include <system_error
#include <iostream
#ifdef _WIN32
#include <windows.h
#endif
bool is_locked_error(const std::error_code& ec) {
#ifdef _WIN32
// Windows: ERROR_SHARING_VIOLATION or ERROR_LOCK_VIOLATION
return ec.value() == ERROR_SHARING_VIOLATION ||
ec.value() == ERROR_LOCK_VIOLATION;
#else
// POSIX: EACCES or EAGAIN may indicate locks in specific filesystems
return ec.value() == EACCES || ec.value() == EAGAIN;
#endif
}
void try_remove(const std::filesystem::path& p) {
std::error_code ec;
std::filesystem::remove(p, ec);
if (ec) {
if (is_locked_error(ec)) {
std::cerr << "File is locked by another process.\n";
} else {
std::cerr << "Removal failed: " << ec.message() << "\n";
}
}
}
system_category. The generic_category maps many OS-specific errors to a small set of portable codes (like std::errc::permission_denied), which often obscures the distinction between a permissions issue and a lock violation.std::filesystem::remove will succeed even if the file is open. The file is removed from the directory entry, but the disk space is not reclaimed until the last process closes the handle. A "lock" error on POSIX is rare and usually limited to specific network filesystems (NFS) or mandatory locking flags.std::error_code overload is preferred over try-catch blocks for expected OS-level collisions, as it avoids the overhead of stack unwinding.Diagnostic Requirement: To refine this further, please specify if you are targeting a specific network filesystem (e.g., SMB/NFS), as these introduce additional error codes not covered by standard local disk behavior.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.