00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: PidFile.cpp 1197 2014-10-14 22:26:11Z sella $";
00010
00011 #include "PidFile.h"
00012
00013 #include <stdio.h>
00014 #include <errno.h>
00015 #include <string.h>
00016 #include <signal.h>
00017 #include <unistd.h>
00018 #include <sys/stat.h>
00019 #include <sys/file.h>
00020
00021 using namespace sella::util;
00022
00023 PidFile::PidFile(const std::string &file, uid_t uid, gid_t gid) throw () : file(file), uid(uid), gid(gid) {
00024 assert(!file.empty());
00025 }
00026
00027 PidFile::PidFile(const PidFile &other) : file(other.file), uid(other.uid), gid(other.gid) {
00028 }
00029
00030 PidFile::~PidFile() {
00031 }
00032
00033 PidFile& PidFile::operator=(const PidFile &other) throw () {
00034 if (this != &other) {
00035 this->file = other.file;
00036 this->uid = other.uid;
00037 this->gid = other.gid;
00038 }
00039
00040 return *this;
00041 }
00042
00043 const std::string& PidFile::get(void) const throw () {
00044 return file;
00045 }
00046
00047 int PidFile::read(void) const throw (PidFileException) {
00048 int pid;
00049 FILE *h;
00050
00051 if ((h = fopen(file.c_str(), "r")) == NULL) {
00052 THROW(PidFileException, "Failed to open file '%s'", file.c_str());
00053 }
00054
00055 if (fscanf(h, "%d", &pid) == EOF) {
00056 THROW(PidFileException, "Failed to read file '%s'", file.c_str());
00057 }
00058
00059 fclose(h);
00060
00061 return pid;
00062 }
00063
00064 int PidFile::write(void) const throw (PidFileException) {
00065 int fd, pid;
00066 FILE *h;
00067
00068 if ((fd = open(file.c_str(), O_RDWR|O_CREAT, 0644)) == -1 || (h = fdopen(fd, "r+")) == NULL) {
00069 THROW(PidFileException, "Failed to open or create file '%s'", file.c_str());
00070 }
00071
00072 if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
00073 if (fscanf(h, "%d", &pid) == EOF) {
00074 pid = -1;
00075 }
00076 fclose(h);
00077
00078 THROW(PidFileException, "Lock on file '%s' is already held by pid %d", file.c_str(), pid);
00079 }
00080
00081 pid = getpid();
00082
00083 if (fprintf(h, "%d\n", pid) < 1) {
00084 close(fd);
00085
00086 THROW2(PidFileException, "Failed to write pid %d to file '%s'", pid, file.c_str());
00087 }
00088
00089 fflush(h);
00090
00091 if (flock(fd, LOCK_UN) == -1) {
00092 THROW2(PidFileException, "Failed to unlock file '%s'", file.c_str());
00093 }
00094
00095 if (uid != (__UID_T_TYPE) -1 || gid != (__GID_T_TYPE) -1) {
00096 if (fchown(fd, uid, gid) != 0) {
00097 THROW2(PidFileException, "Failed to change owner of file '%s' to %d:%d", file.c_str(), uid, gid);
00098 }
00099 }
00100
00101 close(fd);
00102
00103 return pid;
00104 }
00105
00106 void PidFile::remove(void) const throw (PidFileException) {
00107 if (unlink(file.c_str()) != 0) {
00108 THROW2(PidFileException, "Failed to remove file '%s'", file.c_str());
00109 }
00110 }
00111
00112 bool PidFile::isOwner(void) const throw () {
00113 int pid;
00114
00115 try {
00116 pid = read();
00117 } catch (PidFileException) {
00118 return false;
00119 }
00120
00121 return (pid == getpid());
00122 }
00123
00124 bool PidFile::isLive(void) const throw () {
00125 int pid;
00126
00127 try {
00128 pid = read();
00129 } catch (PidFileException) {
00130 return false;
00131 }
00132
00133 if (pid == getpid()) {
00134 return true;
00135 }
00136
00137
00138 if (pid == 0 || (kill(pid, 0) != 0 && errno == ESRCH)) {
00139 return false;
00140 }
00141
00142 return true;
00143 }
00144
00145 bool PidFile::isFile(void) const throw () {
00146 FILE *h;
00147
00148 if ((h = fopen(file.c_str(), "r")) == NULL) {
00149 return false;
00150 }
00151
00152 fclose(h);
00153
00154 return true;
00155 }
00156
00157 const PidFile::shared PidFile::shared_ptr(const std::string &file, uid_t uid, gid_t gid) throw () {
00158 return std::make_shared<PidFile>(file, uid, gid);
00159 }
00160
00161
00162
00163