#include <PidFileLock.h>
Public Member Functions | |
PidFileLock () | |
Constructor. | |
~PidFileLock () | |
Destructor. | |
bool | lock (const string &filename_) |
Lock the file. | |
int | get_error () const |
Return last errno value. | |
const char * | get_error_msg () const |
In case of error, return a verbal description of the last error. | |
void | dump () |
Write the state of the lock to debug file. | |
Private Member Functions | |
pid_t | open_pid_file (const std::string &fname_) |
Open pid file in a cross-platform way. | |
int | lock_region () |
Lock the entire file. | |
int | lock_region_exclusive () |
Lock the entire file (only under Cygwin). | |
int | unlock_region () |
Unlock the entire file. | |
int | get_lock_status () |
Retrieve lock status. | |
int | write_pid () |
Write our process pid to the lock file. | |
pid_t | test_region () |
Test if file is unlocked. | |
void | log_error (const char *msg_) |
Log an error message to the log file and set internal error to errno. | |
Private Attributes | |
string | m_filename |
Lock file name. | |
int | m_fd |
Lock file descriptor. | |
int | m_error |
Last system call error. | |
string | m_error_msg |
Error explanation. |
Definition at line 33 of file PidFileLock.h.
|
Constructor.
Definition at line 32 of file PidFileLock.cpp. References ASSA::PIDFLOCK, and trace_with_mask. 00032 : 00033 m_fd (-1), 00034 m_error (0), 00035 m_error_msg ("no errors") 00036 { 00037 trace_with_mask ("PidFileLock::PidFileLock", PIDFLOCK); 00038 00039 l_whence = SEEK_SET; 00040 l_start = l_len = l_pid = 0; 00041 }
|
|
Destructor. If process is holds the lock on the file, file is removed from the file system. Definition at line 44 of file PidFileLock.cpp. References DL, m_fd, m_filename, ASSA::PIDFLOCK, trace_with_mask, and unlock_region(). 00045 { 00046 trace_with_mask ("PidFileLock::~PidFileLock", PIDFLOCK); 00047 00048 if (m_fd != -1) { 00049 if (unlock_region () == 0) { // if we had a lock 00050 DL((PIDFLOCK,"PID file unlocked.\n")); 00051 00052 unlink (m_filename.c_str ()); 00053 DL((PIDFLOCK,"PID file removed.\n")); 00054 } 00055 close (m_fd); 00056 DL((PIDFLOCK,"PID lock file closed.\n")); 00057 } 00058 }
|
|
Write the state of the lock to debug file.
Definition at line 343 of file PidFileLock.cpp. References DL, get_error(), get_error_msg(), m_fd, m_filename, ASSA::PIDFLOCK, test_region(), and trace_with_mask. 00344 { 00345 trace_with_mask("PidFileLock::dump", PIDFLOCK); 00346 00347 DL((PIDFLOCK,"m_filename : \"%s\"\n", m_filename.c_str())); 00348 DL((PIDFLOCK,"m_error : %d\n", get_error ())); 00349 DL((PIDFLOCK,"m_error_msg: \"%s\"\n", get_error_msg ())); 00350 DL((PIDFLOCK,"m_fd : %d\n", m_fd)); 00351 00352 if (m_fd == -1) return; 00353 00354 test_region (); 00355 00356 if (this->l_type == F_RDLCK) 00357 DL((PIDFLOCK,"l_type : F_RDLCK")); 00358 00359 if (this->l_type == F_WRLCK) 00360 DL((PIDFLOCK,"l_type : F_WRLCK")); 00361 00362 if (this->l_type == F_UNLCK) 00363 DL((PIDFLOCK,"l_type : F_UNLCK")); 00364 00365 DL((PIDFLOCK,"l_whence : %s\n", 00366 this->l_whence == SEEK_SET ? "SEEK_SET" : 00367 this->l_whence == SEEK_CUR ? "SEEK_CUR" : "SEEK_END")); 00368 00369 DL((PIDFLOCK,"l_start : %d\n", this->l_start)); 00370 DL((PIDFLOCK,"l_len : %d\n", this->l_len )); 00371 DL((PIDFLOCK,"l_pid : %ld\n", this->l_pid )); 00372 }
|
|
Return last
Definition at line 124 of file PidFileLock.h. References m_error. Referenced by dump(), and lock(). 00125 { 00126 return m_error; 00127 }
|
|
In case of error, return a verbal description of the last error.
Definition at line 131 of file PidFileLock.h. References m_error_msg. Referenced by dump(). 00132 { 00133 return m_error_msg.c_str (); 00134 }
|
|
Retrieve lock status.
Definition at line 266 of file PidFileLock.cpp. References DL, EL, lock_region_exclusive(), m_fd, ASSA::PIDFLOCK, trace_with_mask, and unlock_region(). Referenced by test_region(). 00267 { 00268 trace_with_mask ("PidFileLock::get_lock_status", PIDFLOCK); 00269 int ret; 00270 00271 #ifndef __CYGWIN__ // POSIX-compliant locking 00272 00273 this->l_type = F_WRLCK; 00274 this->l_start = 0; 00275 this->l_whence = SEEK_SET; 00276 this->l_len = 0; 00277 00278 ret = ::fcntl (m_fd, F_GETLK, static_cast<struct flock*>(this)); 00279 00280 DL((PIDFLOCK,"fcntl(fd=%d, F_GETLK, %s) returned: %d\n", 00281 m_fd, 00282 (this->l_type == F_RDLCK ? "F_RDLCK" : "F_WRLCK"), 00283 ret)); 00284 if (ret < 0) { 00285 EL ((PIDFLOCK,"fcntl() failed. l_pid = %d\n", this->l_pid)); 00286 } 00287 return (ret); 00288 00289 #else // CYGWIN 00290 00291 if (lock_region_exclusive () < 0) { // why exclusive? 00292 if (unlock_region () < 0) { // already locked 00293 char buf[64]; 00294 pid_t pid; // someone else got it 00295 this->l_type = F_RDLCK; 00296 if (read (m_fd, buf, 64) > 0) { 00297 if (sscanf (buf, "%d", &pid) == 1) { 00298 this->l_pid = pid; 00299 } 00300 } 00301 else { 00302 this->l_pid = 1; // no real PID information 00303 } 00304 } 00305 } 00306 else { 00307 unlock_region (); // return the lock into its prestine state 00308 } 00309 return (0); 00310 00311 #endif 00312 }
|
|
Lock the file.
Definition at line 62 of file PidFileLock.cpp. References DL, get_error(), log_error(), m_error, m_fd, m_filename, open_pid_file(), ASSA::PIDFLOCK, ASSA::Utils::strenv(), trace_with_mask, and write_pid(). 00063 { 00064 trace_with_mask ("PidFileLock::lock", PIDFLOCK); 00065 00066 int val; 00067 int len; 00068 m_filename = Utils::strenv (fname_.c_str ()); 00069 val = len = 0; 00070 00071 DL((PIDFLOCK,"PID lock file: \"%s\"\n", m_filename.c_str ())); 00072 00073 if (open_pid_file (m_filename) < 0) { 00074 goto done; 00075 } 00076 DL((PIDFLOCK,"PID lock file opened and locked (fd=%d).\n", m_fd)); 00077 00080 if (ftruncate (m_fd, 0) < 0) { 00081 log_error("ftruncate() error"); 00082 goto done; 00083 } 00084 DL((PIDFLOCK,"PID lock file truncated.\n")); 00085 00088 if (write_pid () < 0) { 00089 log_error("write(PID) error"); 00090 goto done; 00091 } 00092 00095 if ((val = ::fcntl(m_fd, F_GETFD, 0)) < 0) { 00096 log_error("fcntl(F_GETFD) error"); 00097 goto done; 00098 } 00099 val |= FD_CLOEXEC; 00100 00101 if (::fcntl (m_fd, F_SETFD, val) < 0) { 00102 log_error("fcntl(F_SETFD) error"); 00103 goto done; 00104 } 00105 DL((PIDFLOCK,"CLOSE-ON-EXEC is set on FD.\n")); 00106 00107 done: 00108 if (get_error () != 0) { 00109 ::close (m_fd); 00110 m_fd = -1; 00111 } 00112 return m_error == 0 ? true : false; 00113 }
|
|
Lock the entire file.
Definition at line 168 of file PidFileLock.cpp. References DL, m_fd, ASSA::PIDFLOCK, and trace_with_mask. Referenced by open_pid_file(), and write_pid(). 00169 { 00170 trace_with_mask ("PidFileLock::lock_region", PIDFLOCK); 00171 int ret; 00172 00173 #ifdef __CYGWIN__ 00174 this->l_type = F_RDLCK; // shared lock 00175 #else 00176 this->l_type = F_WRLCK; 00177 #endif 00178 00179 this->l_start = 0; 00180 this->l_whence = SEEK_SET; 00181 this->l_len = 0; 00182 00183 ret = ::fcntl (m_fd, F_SETLK, static_cast<struct flock*>(this)); 00184 00185 DL((PIDFLOCK,"fcntl(fd=%d, F_SETLK, %s) returned: %d\n", 00186 m_fd, 00187 (this->l_type == F_RDLCK ? "F_RDLCK" : "F_WRLCK"), 00188 ret)); 00189 00190 return (ret); 00191 }
|
|
Lock the entire file (only under Cygwin).
Definition at line 196 of file PidFileLock.cpp. References DL, m_fd, ASSA::PIDFLOCK, and trace_with_mask. Referenced by get_lock_status(), and write_pid(). 00197 { 00198 trace_with_mask ("PidFileLock::lock_region_exclusive", PIDFLOCK); 00199 int ret = 0; 00200 00201 #ifdef __CYGWIN__ 00202 this->l_type = F_WRLCK; // exclusive lock - read would fail 00203 this->l_start = 0; 00204 this->l_whence = SEEK_SET; 00205 this->l_len = 0; 00206 00207 ret = ::fcntl (m_fd, F_SETLK, static_cast<struct flock*>(this)); 00208 00209 DL((PIDFLOCK,"fcntl(fd=%d, F_SETLK, F_WRLCK) returned: %d\n", m_fd, ret)); 00210 #endif 00211 00212 return (ret); 00213 }
|
|
Log an error message to the log file and set internal error to errno.
Definition at line 376 of file PidFileLock.cpp. References EL, ASSA::ERROR, and m_error. Referenced by lock(), and open_pid_file(). 00377 { 00378 m_error = errno; 00379 EL((ERROR, "Error: \"Failed to get a lock on PID file - %s\".\n", msg_)); 00380 }
|
|
Open pid file in a cross-platform way. If we cannot get lock status, or already have a lock, or if PID file is already locked by another process, then terminate. Otherwise (file is unlocked), proceed with locking. Try to set a write lock on the entire file Definition at line 389 of file PidFileLock.cpp. References lock_region(), log_error(), m_error, m_fd, ASSA::PIDFLOCK, test_region(), and trace_with_mask. Referenced by lock(). 00390 { 00391 trace_with_mask("PidFileLock::open_pid_file", PIDFLOCK); 00392 00393 m_fd = ::open (fname_.c_str (), O_WRONLY|O_CREAT, 0644); 00394 if (m_fd < 0) { 00395 log_error("open() error."); 00396 return -1; 00397 } 00398 00403 pid_t owner_pid; 00404 if ((owner_pid = test_region ()) > 0) { 00405 log_error ("PID file is already locked (by someone)."); 00406 m_error = EPERM; 00407 return -1; 00408 } 00409 00412 if (lock_region () < 0) { 00413 if (errno == EACCES || errno == EAGAIN) { 00414 log_error("PID file is locked by another process"); 00415 } 00416 else { 00417 log_error("write lock error"); 00418 } 00419 return -1; 00420 } 00421 00422 return 0; 00423 }
|
|
Test if file is unlocked.
Definition at line 320 of file PidFileLock.cpp. References DL, get_lock_status(), ASSA::PIDFLOCK, and trace_with_mask. Referenced by dump(), and open_pid_file(). 00321 { 00322 trace_with_mask ("PidFileLock::test_region", PIDFLOCK); 00323 int ret; 00324 00325 ret = get_lock_status (); 00326 00327 if (ret < 0) { 00328 DL((PIDFLOCK,"Failed to retrieve lock status.\n")); 00329 return 1; 00330 } 00331 if (this->l_type == F_UNLCK) { 00332 DL((PIDFLOCK,"Region is not locked.\n")); 00333 return(0); 00334 } 00335 00336 DL((PIDFLOCK,"Region is already locked by PID %d\n", this->l_pid)); 00337 return (this->l_pid); 00338 }
|
|
Unlock the entire file.
Definition at line 217 of file PidFileLock.cpp. References DL, m_fd, ASSA::PIDFLOCK, and trace_with_mask. Referenced by get_lock_status(), write_pid(), and ~PidFileLock(). 00218 { 00219 trace_with_mask ("PidFileLock::unlock_region", PIDFLOCK); 00220 int ret; 00221 00222 this->l_type = F_UNLCK; 00223 this->l_start = 0; 00224 this->l_whence = SEEK_SET; 00225 this->l_len = 0; 00226 00227 ret = ::fcntl (m_fd, F_SETLK, static_cast<struct flock*>(this)); 00228 00229 DL((PIDFLOCK,"fcntl(fd=%d, F_SETLK, F_UNLCK) returned: %d\n", 00230 m_fd, ret)); 00231 00232 return (ret); 00233 }
|
|
Write our process pid to the lock file.
Definition at line 127 of file PidFileLock.cpp. References DL, ASSA::ends(), lock_region(), lock_region_exclusive(), m_fd, ASSA::PIDFLOCK, trace_with_mask, and unlock_region(). Referenced by lock(). 00128 { 00129 trace_with_mask ("PidFileLock::write_pid", PIDFLOCK); 00130 00131 std::ostringstream mypid; 00132 size_t len; 00133 00134 this->l_pid = getpid (); 00135 mypid << this->l_pid << std::ends; 00136 len = strlen (mypid.str ().c_str ()); 00137 00138 #ifdef __CYGWIN__ 00139 00140 unlock_region (); // remove shared (weak) lock 00141 lock_region_exclusive (); 00142 00143 if (write (m_fd, mypid.str ().c_str (), len) != len) { 00144 return -1; 00145 } 00146 DL((PIDFLOCK,"Wrote PID=%d to the lock file.\n", l_pid)); 00147 unlock_region (); // give up the exclusive lock 00148 lock_region (); // place shared (weak) lock 00149 00150 #else // POSIX-compliant locks 00151 00152 if (write (m_fd, mypid.str ().c_str (), len) != len) { 00153 return -1; 00154 } 00155 DL((PIDFLOCK,"Wrote PID=%d to the lock file.\n", this->l_pid)); 00156 00157 #endif 00158 return 0; 00159 }
|
|
Last system call error.
Definition at line 116 of file PidFileLock.h. Referenced by get_error(), lock(), log_error(), and open_pid_file(). |
|
Error explanation.
Definition at line 119 of file PidFileLock.h. Referenced by get_error_msg(). |
|
Lock file descriptor.
Definition at line 113 of file PidFileLock.h. Referenced by dump(), get_lock_status(), lock(), lock_region(), lock_region_exclusive(), open_pid_file(), unlock_region(), write_pid(), and ~PidFileLock(). |
|
Lock file name.
Definition at line 110 of file PidFileLock.h. Referenced by dump(), lock(), and ~PidFileLock(). |