Skip to content

Commit

Permalink
iox-eclipse-iceoryx#1216 File lock releases file lock on dtor and rem…
Browse files Browse the repository at this point in the history
…oves file

Signed-off-by: Christian Eltzschig <me@elchris.org>
  • Loading branch information
elfenpiff committed Mar 3, 2022
1 parent b781ed0 commit 6b4904e
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,15 @@ class FileLock : public DesignPattern::Creation<FileLock, FileLockError>

private:
int32_t m_fd{INVALID_FD};
FileName_t m_name{""};
FileName_t m_name;
PathName_t m_fileLockPath;

/// @brief c'tor
/// @param[in] name of the created file lock in PATH_PREFIX
FileLock(const FileName_t& name) noexcept;

void invalidate() noexcept;

cxx::expected<FileLockError> initializeFileLock() noexcept;
FileLockError convertErrnoToFileLockError(const int32_t errnum) const noexcept;
cxx::expected<FileLockError> closeFileDescriptor() noexcept;
Expand Down
92 changes: 58 additions & 34 deletions iceoryx_hoofs/source/posix_wrapper/file_lock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace posix
{
FileLock::FileLock(const FileName_t& name) noexcept
: m_name(name)
, m_fileLockPath(platform::IOX_LOCK_FILE_PATH_PREFIX + m_name + LOCK_FILE_SUFFIX)
{
initializeFileLock().and_then([this]() { this->m_isInitialized = true; }).or_else([this](FileLockError& error) {
this->m_isInitialized = false;
Expand All @@ -44,11 +45,10 @@ cxx::expected<FileLockError> FileLock::initializeFileLock() noexcept
{
return cxx::error<FileLockError>(FileLockError::INVALID_FILE_NAME);
}
PathName_t fullPath(platform::IOX_LOCK_FILE_PATH_PREFIX + m_name + ".lock");
constexpr int CREATE_FILE_FOR_READ_WRITE = O_CREAT | O_RDWR;
mode_t userReadWriteAccess = S_IRUSR | S_IWUSR;

auto openCall = posixCall(iox_open)(fullPath.c_str(), CREATE_FILE_FOR_READ_WRITE, userReadWriteAccess)
auto openCall = posixCall(iox_open)(m_fileLockPath.c_str(), CREATE_FILE_FOR_READ_WRITE, userReadWriteAccess)
.failureReturnValue(ERROR_CODE)
.evaluate()
.and_then([this](auto& r) { this->m_fd = r.value; });
Expand Down Expand Up @@ -86,17 +86,17 @@ FileLock& FileLock::operator=(FileLock&& rhs) noexcept
{
if (closeFileDescriptor().has_error())
{
std::cerr << "Unable to cleanup file lock \"" << m_name
std::cerr << "Unable to cleanup file lock \"" << m_fileLockPath
<< "\" in the move constructor/move assingment operator" << std::endl;
}

CreationPattern_t::operator=(std::move(rhs));

m_name = std::move(rhs.m_name);
m_fileLockPath = std::move(rhs.m_fileLockPath);
m_fd = std::move(rhs.m_fd);

rhs.m_name.assign("");
rhs.m_fd = INVALID_FD;
rhs.invalidate();
}

return *this;
Expand All @@ -106,80 +106,104 @@ FileLock::~FileLock() noexcept
{
if (closeFileDescriptor().has_error())
{
std::cerr << "unable to cleanup file lock \"" << m_name << "\" in the destructor" << std::endl;
std::cerr << "unable to cleanup file lock \"" << m_fileLockPath << "\" in the destructor" << std::endl;
}
}

cxx::expected<FileLockError> FileLock::closeFileDescriptor() noexcept
{
if (isInitialized() && (m_fd != INVALID_FD))
{
auto closeCall = posixCall(iox_close)(m_fd).failureReturnValue(ERROR_CODE).evaluate();
bool cleanupFailed = false;
posixCall(iox_flock)(m_fd, LOCK_UN)
.failureReturnValue(ERROR_CODE)
.suppressErrorMessagesForErrnos(EWOULDBLOCK)
.evaluate()
.or_else([&](auto& result) {
cleanupFailed = true;
IOX_DISCARD_RESULT(convertErrnoToFileLockError(result.errnum));
std::cerr << "Unable to unlock the file lock \"" << m_fileLockPath << "\"" << std::endl;
});

m_fd = INVALID_FD;
m_isInitialized = false;
posixCall(iox_close)(m_fd).failureReturnValue(ERROR_CODE).evaluate().or_else([&](auto& result) {
cleanupFailed = true;
IOX_DISCARD_RESULT(convertErrnoToFileLockError(result.errnum));
std::cerr << "Unable to close the file handle to the file lock \"" << m_fileLockPath << "\"" << std::endl;
});

if (!closeCall.has_error())
{
return cxx::success<void>();
}
else
posixCall(remove)(m_fileLockPath.c_str()).failureReturnValue(ERROR_CODE).evaluate().or_else([&](auto& result) {
cleanupFailed = true;
IOX_DISCARD_RESULT(convertErrnoToFileLockError(result.errnum));
std::cerr << "Unable to remove the file lock \"" << m_fileLockPath << "\"" << std::endl;
});

invalidate();

if (cleanupFailed)
{
return cxx::error<FileLockError>(convertErrnoToFileLockError(closeCall.get_error().errnum));
return cxx::error<FileLockError>(FileLockError::INTERNAL_LOGIC_ERROR);
}
}
return cxx::success<>();
}

void FileLock::invalidate() noexcept
{
m_fd = INVALID_FD;
m_isInitialized = false;
m_name.assign("");
m_fileLockPath.assign("");
}

FileLockError FileLock::convertErrnoToFileLockError(const int32_t errnum) const noexcept
{
switch (errnum)
{
case EACCES:
{
std::cerr << "permission to access file denied \"" << m_name << "\"" << std::endl;
std::cerr << "permission to access file denied \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::ACCESS_DENIED;
}
case EDQUOT:
{
std::cerr << "user disk quota exhausted for file \"" << m_name << "\"" << std::endl;
std::cerr << "user disk quota exhausted for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::QUOTA_EXHAUSTED;
}
case EFAULT:
{
std::cerr << "outside address space error for file \"" << m_name << "\"" << std::endl;
std::cerr << "outside address space error for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::ACCESS_DENIED;
}
case EFBIG:
case EOVERFLOW:
{
std::cerr << "file \"" << m_name << "\""
std::cerr << "file \"" << m_fileLockPath << "\""
<< " is too large to be openend" << std::endl;
return FileLockError::FILE_TOO_LARGE;
}
case EINVAL:
{
std::cerr << "provided invalid characters in file \"" << m_name << "\"" << std::endl;
std::cerr << "provided invalid characters in file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::INVALID_CHARACTERS_IN_FILE_NAME;
}
case ELOOP:
{
std::cerr << "too many symbolic links for file \"" << m_name << "\"" << std::endl;
std::cerr << "too many symbolic links for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::INVALID_FILE_NAME;
}
case EMFILE:
{
std::cerr << "process limit reached for file \"" << m_name << "\"" << std::endl;
std::cerr << "process limit reached for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::PROCESS_LIMIT;
}
case ENFILE:
{
std::cerr << "system limit reached for file \"" << m_name << "\"" << std::endl;
std::cerr << "system limit reached for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::SYSTEM_LIMIT;
}
case ENODEV:
{
std::cerr << "permission to access file denied \"" << m_name << "\"" << std::endl;
std::cerr << "permission to access file denied \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::ACCESS_DENIED;
}
case ENOENT:
Expand All @@ -191,38 +215,38 @@ FileLockError FileLock::convertErrnoToFileLockError(const int32_t errnum) const
}
case ENOMEM:
{
std::cerr << "out of memory for file \"" << m_name << "\"" << std::endl;
std::cerr << "out of memory for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::OUT_OF_MEMORY;
}
case ENOSPC:
{
std::cerr << "Device has no space for file \"" << m_name << "\"" << std::endl;
std::cerr << "Device has no space for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::QUOTA_EXHAUSTED;
}
case ENOSYS:
{
std::cerr << "open() not implemented for filesystem to \"" << m_name << "\"" << std::endl;
std::cerr << "open() not implemented for filesystem to \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::SYS_CALL_NOT_IMPLEMENTED;
}
case ENXIO:
{
std::cerr << "\"" << m_name << "\""
std::cerr << "\"" << m_fileLockPath << "\""
<< " is a special file and no corresponding device exists" << std::endl;
return FileLockError::SPECIAL_FILE;
}
case EPERM:
{
std::cerr << "permission to access file denied \"" << m_name << "\"" << std::endl;
std::cerr << "permission to access file denied \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::ACCESS_DENIED;
}
case EROFS:
{
std::cerr << "read only error for file \"" << m_name << "\"" << std::endl;
std::cerr << "read only error for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::INVALID_FILE_NAME;
}
case ETXTBSY:
{
std::cerr << "write access requested for file \"" << m_name << "\""
std::cerr << "write access requested for file \"" << m_fileLockPath << "\""
<< " in use" << std::endl;
return FileLockError::FILE_IN_USE;
}
Expand All @@ -233,17 +257,17 @@ FileLockError FileLock::convertErrnoToFileLockError(const int32_t errnum) const
}
case ENOLCK:
{
std::cerr << "system limit for locks reached for file \"" << m_name << "\"" << std::endl;
std::cerr << "system limit for locks reached for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::SYSTEM_LIMIT;
}
case EIO:
{
std::cerr << "I/O for file \"" << m_name << "\"" << std::endl;
std::cerr << "I/O for file \"" << m_fileLockPath << "\"" << std::endl;
return FileLockError::I_O_ERROR;
}
default:
{
std::cerr << "internal logic error in file \"" << m_name << "\" occurred" << std::endl;
std::cerr << "internal logic error in file \"" << m_fileLockPath << "\" occurred" << std::endl;
return FileLockError::INTERNAL_LOGIC_ERROR;
}
}
Expand Down

0 comments on commit 6b4904e

Please sign in to comment.