From f32fb1b3f1dd6cd89e7345c8592bcfaeaa559b85 Mon Sep 17 00:00:00 2001 From: prozacx Date: Sun, 24 Apr 2005 05:53:07 +0000 Subject: [PATCH] Changed from checking pidfile to locking the config git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@177 726aef4b-f618-498e-8847-2d620e286838 --- Utils.h | 192 +++++++++++++++++++++++++++++++++++++++++++++----------- znc.cpp | 53 +++------------- znc.h | 2 +- 3 files changed, 165 insertions(+), 82 deletions(-) diff --git a/Utils.h b/Utils.h index 618dffc8..a2d22e01 100644 --- a/Utils.h +++ b/Utils.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include @@ -19,8 +21,7 @@ using std::map; static const char g_HexDigits[] = "0123456789abcdef"; -class CUtils -{ +class CUtils { public: CUtils(); virtual ~CUtils(); @@ -56,14 +57,133 @@ public: static string Token(const string& s, unsigned int uPos, bool bRest = false, char cSep = ' '); static string Ellipsize(const string& s, unsigned int uLen); static bool wildcmp(const string& sWild, const string& sString); + + static unsigned long long GetMillTime() { + struct timeval tv; + unsigned long long iTime = 0; + gettimeofday(&tv, NULL); + iTime = (unsigned long long) tv.tv_sec * 1000; + iTime += ((unsigned long long) tv.tv_usec / 1000); + return iTime; + } #ifdef HAVE_LIBSSL - static void GenerateCert( FILE *pOut, bool bEncPrivKey = false ); + static void GenerateCert(FILE *pOut, bool bEncPrivKey = false); #endif /* HAVE_LIBSSL */ - + private: protected: }; +class CLockFile { +public: + CLockFile() { + m_bCreated = false; + m_fd = 0; + m_pid = 0; + } + + CLockFile(const string& sFile) { + Open(sFile); + } + + virtual ~CLockFile() { + if (getpid() == m_pid) { + if (m_fd > -1) { + UnLock(); + close(m_fd); + if (m_bCreated) { + unlink(m_sFileName.c_str()); + } + } + } + } + + void Open(const string& sFile) { + m_fd = open(sFile.c_str(), O_RDONLY); + m_bCreated = false; + + if (m_fd == -1) { + // i must create the file then + m_fd = open(sFile.c_str(), O_RDWR|O_CREAT, 0644); + m_bCreated = true; + } + + m_pid = getpid(); // for destructor + m_sFileName = sFile; + } + + //! timeout in milliseconds + bool TryExLock(const string& sLockFile, unsigned long long iTimeout = 0) { + Open(sLockFile); + return TryExLock(iTimeout); + } + + bool TryExLock(unsigned long long iTimeout = 0) { + if (iTimeout == 0) { + return Lock(LOCK_EX|LOCK_NB); + } + + unsigned long long iNow = CUtils::GetMillTime(); + + while(true) { + if (Lock(LOCK_EX|LOCK_NB)) { + return true; + } + + if ((CUtils::GetMillTime() - iNow) > iTimeout) { + break; + } + + usleep(100); + } + + return(false); + } + + bool TryShLock(unsigned long long iTimeout = 0) { + if (iTimeout == 0) { + return(Lock(LOCK_SH|LOCK_NB)); + } + + unsigned long long iNow = CUtils::GetMillTime(); + + while(true) { + if (Lock(LOCK_SH|LOCK_NB)) { + return true; + } + + if ((CUtils::GetMillTime() - iNow) > iTimeout) { + break; + } + + usleep(100); + } + + return false; + } + + bool LockEx() { return Lock(LOCK_EX); } + bool LockSh() { return Lock(LOCK_SH); } + bool UnLock() { return Lock(LOCK_UN); } + +private: + bool Lock(int iOperation) { + if (m_fd == -1) { + return false; + } + + if (::flock(m_fd, iOperation) != 0) { + return false; + } + + return true; + } + + int m_fd; + int m_pid; + bool m_bCreated; + string m_sFileName; +}; class CException { public: @@ -106,8 +226,7 @@ public: CFile(const string& sLongName); virtual ~CFile(); - enum EFileTypes - { + enum EFileTypes { FT_REGULAR, FT_DIRECTORY, FT_CHARACTER, @@ -117,26 +236,26 @@ public: FT_SOCK }; - static bool IsReg( const string& sLongName, bool bUseLstat = false ); - static bool IsDir( const string& sLongName, bool bUseLstat = false ); - static bool IsChr( const string& sLongName, bool bUseLstat = false ); - static bool IsBlk( const string& sLongName, bool bUseLstat = false ); - static bool IsFifo( const string& sLongName, bool bUseLstat = false ); - static bool IsLnk( const string& sLongName, bool bUseLstat = true ); - static bool IsSock( const string& sLongName, bool bUseLstat = false ); + static bool IsReg(const string& sLongName, bool bUseLstat = false); + static bool IsDir(const string& sLongName, bool bUseLstat = false); + static bool IsChr(const string& sLongName, bool bUseLstat = false); + static bool IsBlk(const string& sLongName, bool bUseLstat = false); + static bool IsFifo(const string& sLongName, bool bUseLstat = false); + static bool IsLnk(const string& sLongName, bool bUseLstat = true); + static bool IsSock(const string& sLongName, bool bUseLstat = false); - bool IsReg( bool bUseLstat = false ); - bool IsDir( bool bUseLstat = false ); - bool IsChr( bool bUseLstat = false ); - bool IsBlk( bool bUseLstat = false ); - bool IsFifo( bool bUseLstat = false ); - bool IsLnk( bool bUseLstat = true ); - bool IsSock( bool bUseLstat = false ); + bool IsReg(bool bUseLstat = false); + bool IsDir(bool bUseLstat = false); + bool IsChr(bool bUseLstat = false); + bool IsBlk(bool bUseLstat = false); + bool IsFifo(bool bUseLstat = false); + bool IsLnk(bool bUseLstat = true); + bool IsSock(bool bUseLstat = false); - bool access( int mode ); + bool access(int mode); // for gettin file types, using fstat instead - static bool FType( const string sFileName, EFileTypes eType, bool bUseLstat = false ); + static bool FType(const string sFileName, EFileTypes eType, bool bUseLstat = false); enum EFileAttr { FA_Name, @@ -178,16 +297,16 @@ public: bool Chmod(mode_t mode); static bool Chmod(const string& sFile, mode_t mode); bool Seek(unsigned long uPos); - bool Open( int iFlags, mode_t iMode = 0644 ); - int Read( char *pszBuffer, int iBytes ); - bool ReadLine( string & sData ); - int Write( const char *pszBuffer, u_int iBytes ); - int Write( const string & sData ); + bool Open(int iFlags, mode_t iMode = 0644); + int Read(char *pszBuffer, int iBytes); + bool ReadLine(string & sData); + int Write(const char *pszBuffer, u_int iBytes); + int Write(const string & sData); void Close(); string GetLongName() const; string GetShortName() const; - void SetFD( int iFD ); + void SetFD(int iFD); private: string m_sBuffer; @@ -203,8 +322,7 @@ protected: #include #include //! does Blowfish w/64 bit feedback, no padding -class CBlowfish -{ +class CBlowfish { public: /** * @sPassword key to encrypt with @@ -217,7 +335,7 @@ public: //! output must be freed static unsigned char *MD5(const unsigned char *input, u_int ilen); - //! returns an md5 of the string ( not hex encoded ) + //! returns an md5 of the string (not hex encoded) static string MD5(const string & sInput, bool bHexEncode = false); //! output must be the same size as input @@ -241,9 +359,9 @@ inline bool ReadFile(const string & sFilename, string & sLine) { int bytes; // clear ourselves out sLine.clear(); - + FILE *f = fopen(sFilename.c_str(), "r"); - + if (!f) { return false; } @@ -251,12 +369,12 @@ inline bool ReadFile(const string & sFilename, string & sLine) { while((bytes = fread(inbuff, sizeof(char), RF_BUFF, f)) > 0) { sLine.append(inbuff, bytes); } - + fclose(f); if (bytes < 0) { return false; } - + return true; } @@ -269,7 +387,7 @@ inline bool WriteFile(const string & sFilename, const string & sData) { int iRet = fwrite(sData.data(), sizeof(char), sData.length(), f); fclose(f); - + if (iRet <= 0) { return false; } @@ -312,7 +430,7 @@ inline string Upper(const string & sLine) { for(u_int a = 0; a < sLine.length(); a++) { sRet += toupper(sLine[a]); } - + return sRet; } diff --git a/znc.cpp b/znc.cpp index 79d49d26..efa19168 100644 --- a/znc.cpp +++ b/znc.cpp @@ -126,46 +126,6 @@ void CZNC::ReleaseISpoof() { m_bISpoofLocked = false; } -bool CZNC::SetPidFile(const string& sFile) { - CUtils::PrintAction("Checking PidFile [" + sFile + "]"); - - if (!sFile.empty() && sFile[0] != '/') { - m_sPidFile = GetZNCPath() + "/" + sFile; - } else { - m_sPidFile = sFile; - } - - if (!m_sPidFile.empty()) { - unsigned int uPid = 0; - CFile File(m_sPidFile); - - if (File.Open(O_RDONLY)) { - string sPid; - - if (File.ReadLine(sPid)) { - uPid = atoi(sPid.c_str()); - - if (uPid > 0 && kill(uPid, 0) == 0) { - CUtils::PrintStatus(false, "ZNC already running [pid: " + CUtils::ToString(uPid) + "]"); - File.Close(); - - return false; - } else { - CUtils::PrintStatus(true, "Stale pid, relaunching"); - File.Close(); - - return true; - } - } - - File.Close(); - } - } - - CUtils::PrintStatus(true); - return true; -} - bool CZNC::WritePidFile(int iPid) { if (!m_sPidFile.empty()) { CFile File(m_sPidFile); @@ -270,6 +230,11 @@ bool CZNC::ParseConfig(const string& sConfigFile) { CUtils::PrintAction("Opening Config [" + sFilePath + "]"); + if (!m_LockFile.TryExLock(sFilePath, 50)) { + CUtils::PrintStatus(false, "ZNC is already running on this config."); + return false; + } + CFile File(sFilePath); if (!File.Open(O_RDONLY)) { @@ -526,10 +491,10 @@ bool CZNC::ParseConfig(const string& sConfigFile) { m_sISpoofFile = sValue; continue; } else if (strcasecmp(sName.c_str(), "PidFile") == 0) { - if (!sValue.empty()) { - if (!SetPidFile(sValue)) { - return false; - } + if (!sValue.empty() && sValue[0] != '/') { + m_sPidFile = GetZNCPath() + "/" + sValue; + } else { + m_sPidFile = sValue; } continue; diff --git a/znc.h b/znc.h index 0b19fe37..3fe9d257 100644 --- a/znc.h +++ b/znc.h @@ -16,7 +16,6 @@ public: void DeleteUsers(); int Loop(); void ReleaseISpoof(); - bool SetPidFile(const string& sFile); bool WritePidFile(int iPid); CUser* GetUser(const string& sUser); Csock* FindSockByName(const string& sSockName); @@ -67,6 +66,7 @@ protected: string m_sISpoofFile; string m_sOrigISpoof; string m_sPidFile; + CLockFile m_LockFile; bool m_bISpoofLocked; bool m_bSSL; map::iterator m_itUserIter; // This needs to be reset to m_msUsers.begin() if anything is added or removed to the map