diff options
| author | Maksym Telychko <maksym.telychko@globallogic.com> | 2020-03-24 17:41:04 +0200 | 
|---|---|---|
| committer | Andrii Pientsov <andrii.pientsov@globallogic.com> | 2020-05-26 19:48:31 +0300 | 
| commit | 620bd2637b40d718dd5886ce7df0a19b73ea8875 (patch) | |
| tree | a1937c07a912e8c0b079b4ba3b6aa1dd82aec675 /src | |
| parent | b3a9a71afdb0d6f4f104543cedba89d011ca68df (diff) | |
| download | libmts-io-620bd2637b40d718dd5886ce7df0a19b73ea8875.tar.gz libmts-io-620bd2637b40d718dd5886ce7df0a19b73ea8875.tar.bz2 libmts-io-620bd2637b40d718dd5886ce7df0a19b73ea8875.zip | |
MTX-3262 mpower: lockfile rewrite for interprocess communication safety
Previous implementation was not thread/interprocess safe due to pid
management
Fixes: Single instance guard.
Diffstat (limited to 'src')
| -rw-r--r-- | src/MTS_IO_LockFile.cpp | 92 | 
1 files changed, 25 insertions, 67 deletions
| diff --git a/src/MTS_IO_LockFile.cpp b/src/MTS_IO_LockFile.cpp index b74ba73..4312ce4 100644 --- a/src/MTS_IO_LockFile.cpp +++ b/src/MTS_IO_LockFile.cpp @@ -18,9 +18,9 @@   *   */ -/*!  +/*!   \file MTS_IO_LockFile.cpp - \brief A brief description  + \brief A brief description   \date Oct 8, 2014   \author sgodinez @@ -29,13 +29,7 @@  #include <mts/MTS_IO_LockFile.h>  #include <mts/MTS_Timer.h> -#include <mts/MTS_Logger.h> -#include <mts/MTS_System.h> -#include <mts/MTS_Text.h>  #include <sys/file.h> -#include <sys/stat.h> -#include <errno.h> -#include <string.h>  #include <unistd.h>  using namespace MTS::IO; @@ -43,79 +37,43 @@ using namespace MTS::IO;  LockFile::LockFile(const std::string& sFile)  : m_sFile(sFile)  , m_iLockFd(-1) +, m_iLockErr(-1)  { -  } -LockFile::~LockFile() { +LockFile::~LockFile() +{      unlock();  } -bool LockFile::lock(uint32_t attemptMillis) { -    if(isLocked()) { +bool LockFile::lock(uint32_t attemptMillis) +{ +    if (isLocked())          return true; -    }      MTS::Timer timer; -      timer.start(); -    while(timer.getMillis() < attemptMillis) { -        m_iLockFd =::open(m_sFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644); -        if (m_iLockFd < 0) { -            // device already locked -> bail out -            printWarning("LockFile| Failed to Lock [%s] [%d][%s]", m_sFile.c_str(), errno, strerror(errno)); - -            //Check if lock file's process still exists -            std::string sResult; -            if(MTS::System::readFile(m_sFile, sResult) == 0 && sResult.size() > 0) { -                struct stat sts; -                std::string sProc = "/proc/" + MTS::Text::trim(sResult); -                if (stat(sProc.c_str(), &sts) == -1 && errno == ENOENT) { -                    printWarning("LockFile| Current Lock's Process [%s] does not exist.  Removing lock.", sResult.c_str()); -                    // process doesn't exist -> remove file -                    ::unlink(m_sFile.c_str()); -                } -            } - -        } else { -            //TODO: Investigate using flock in addition to minicom-style lock : flock(m_iLockFd, LOCK_EX | LOCK_NB); - -            // %4d to make concurrent mgetty (if any) happy. -            // Mgetty treats 4-bytes lock files as binary, -            // not text, PID. Making 5+ char file. Brrr... -            char buf[256] = {0}; -            size_t written = 0; - -            sprintf(buf, "%4d\n", getpid()); -            size_t wsize = strlen(buf); - -            written = write(m_iLockFd, buf, wsize); - -            if (wsize != written) { -                printError("LockFile| Error writing to lock file [%s] [%d][%s]", m_sFile.c_str(), errno, strerror(errno)); -                close(m_iLockFd); -                return false; -            } -            else { -                close(m_iLockFd); -                return true; -            } -        } -        uint32_t randomSleepTime = ((rand() % 10) + 1) * 100000; //Sleep from 100ms to 1 Second -        ::usleep(randomSleepTime); +    m_iLockFd = ::open(m_sFile.c_str(), O_CREAT | O_RDWR, 0666); +    while (timer.getMillis() < attemptMillis) { +        m_iLockErr = ::flock(m_iLockFd, LOCK_EX | LOCK_NB); +        if (m_iLockErr == 0) +            return true; +        ::usleep(((rand() % 10) + 1) * 100000); //Sleep from 100ms to 1 Second      } +    ::close(m_iLockFd); +    m_iLockFd = -1;      return false;  } -void LockFile::unlock() { -    if(isLocked()) { -        ::unlink(m_sFile.c_str()); -        //TODO: flock cleanup : flock(m_iLockFd, LOCK_UN); -        m_iLockFd = -1; -    } +void LockFile::unlock() +{ +    ::flock(m_iLockFd, LOCK_UN); +    ::close(m_iLockFd); +    m_iLockFd = -1; +    m_iLockErr = -1;  } -bool LockFile::isLocked() { -    return m_iLockFd >= 0; +bool LockFile::isLocked() +{ +    return m_iLockErr == 0;  } - | 
