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
This commit is contained in:
prozacx
2005-04-24 05:53:07 +00:00
parent 38c142ea1e
commit f32fb1b3f1
3 changed files with 165 additions and 82 deletions

192
Utils.h
View File

@@ -3,6 +3,8 @@
#include <unistd.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/file.h>
#include <string>
#include <vector>
@@ -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 <openssl/blowfish.h>
#include <openssl/md5.h>
//! 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;
}

53
znc.cpp
View File

@@ -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;

2
znc.h
View File

@@ -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<string,CUser*>::iterator m_itUserIter; // This needs to be reset to m_msUsers.begin() if anything is added or removed to the map