#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 43 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 384 of file PidFileLock.cpp. References DL, get_error(), get_error_msg(), m_fd, m_filename, ASSA::PIDFLOCK, test_region(), and trace_with_mask. 00385 { 00386 trace_with_mask("PidFileLock::dump", PIDFLOCK); 00387 00388 #if !defined (WIN32) 00389 00390 DL((PIDFLOCK,"m_filename : \"%s\"\n", m_filename.c_str())); 00391 DL((PIDFLOCK,"m_error : %d\n", get_error ())); 00392 DL((PIDFLOCK,"m_error_msg: \"%s\"\n", get_error_msg ())); 00393 DL((PIDFLOCK,"m_fd : %d\n", m_fd)); 00394 00395 if (m_fd == -1) return; 00396 00397 test_region (); 00398 00399 if (this->l_type == F_RDLCK) 00400 DL((PIDFLOCK,"l_type : F_RDLCK")); 00401 00402 if (this->l_type == F_WRLCK) 00403 DL((PIDFLOCK,"l_type : F_WRLCK")); 00404 00405 if (this->l_type == F_UNLCK) 00406 DL((PIDFLOCK,"l_type : F_UNLCK")); 00407 00408 DL((PIDFLOCK,"l_whence : %s\n", 00409 this->l_whence == SEEK_SET ? "SEEK_SET" : 00410 this->l_whence == SEEK_CUR ? "SEEK_CUR" : "SEEK_END")); 00411 00412 DL((PIDFLOCK,"l_start : %d\n", this->l_start)); 00413 DL((PIDFLOCK,"l_len : %d\n", this->l_len )); 00414 DL((PIDFLOCK,"l_pid : %ld\n", this->l_pid )); 00415 00416 #endif // !def WIN32 00417 }
|
|
Return last
Definition at line 134 of file PidFileLock.h. References m_error. Referenced by dump(), and lock(). 00135 { 00136 return m_error; 00137 }
|
|
In case of error, return a verbal description of the last error.
Definition at line 141 of file PidFileLock.h. References m_error_msg. Referenced by dump(). 00142 { 00143 return m_error_msg.c_str (); 00144 }
|
|
Retrieve lock status.
Definition at line 294 of file PidFileLock.cpp. References DL, EL, lock_region_exclusive(), m_fd, ASSA::PIDFLOCK, trace_with_mask, and unlock_region(). Referenced by test_region(). 00295 { 00296 trace_with_mask ("PidFileLock::get_lock_status", PIDFLOCK); 00297 int ret; 00298 00299 #if defined (WIN32) 00300 return 0; 00301 #else 00302 00303 #ifndef __CYGWIN__ // POSIX-compliant locking 00304 00305 this->l_type = F_WRLCK; 00306 this->l_start = 0; 00307 this->l_whence = SEEK_SET; 00308 this->l_len = 0; 00309 00310 ret = ::fcntl (m_fd, F_GETLK, static_cast<struct flock*>(this)); 00311 00312 DL((PIDFLOCK,"fcntl(fd=%d, F_GETLK, %s) returned: %d\n", 00313 m_fd, 00314 (this->l_type == F_RDLCK ? "F_RDLCK" : "F_WRLCK"), 00315 ret)); 00316 if (ret < 0) { 00317 EL ((PIDFLOCK,"fcntl() failed. l_pid = %d\n", this->l_pid)); 00318 } 00319 return (ret); 00320 00321 #else // CYGWIN 00322 00323 if (lock_region_exclusive () < 0) { // why exclusive? 00324 if (unlock_region () < 0) { // already locked 00325 char buf[64]; 00326 pid_t pid; // someone else got it 00327 this->l_type = F_RDLCK; 00328 if (read (m_fd, buf, 64) > 0) { 00329 if (sscanf (buf, "%d", &pid) == 1) { 00330 this->l_pid = pid; 00331 } 00332 } 00333 else { 00334 this->l_pid = 1; // no real PID information 00335 } 00336 } 00337 } 00338 else { 00339 unlock_region (); // return the lock into its prestine state 00340 } 00341 return (0); 00342 00343 #endif // !def CYGWIN 00344 00345 #endif // !def WIN32 00346 00347 }
|
|
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 #if defined(WIN32) 00067 return true; 00068 #else 00069 int val; 00070 int len; 00071 m_filename = Utils::strenv (fname_.c_str ()); 00072 val = len = 0; 00073 00074 DL((PIDFLOCK,"PID lock file: \"%s\"\n", m_filename.c_str ())); 00075 00076 if (open_pid_file (m_filename) < 0) { 00077 goto done; 00078 } 00079 DL((PIDFLOCK,"PID lock file opened and locked (fd=%d).\n", m_fd)); 00080 00083 if (ftruncate (m_fd, 0) < 0) { 00084 log_error("ftruncate() error"); 00085 goto done; 00086 } 00087 DL((PIDFLOCK,"PID lock file truncated.\n")); 00088 00091 if (write_pid () < 0) { 00092 log_error("write(PID) error"); 00093 goto done; 00094 } 00095 00098 if ((val = ::fcntl(m_fd, F_GETFD, 0)) < 0) { 00099 log_error("fcntl(F_GETFD) error"); 00100 goto done; 00101 } 00102 val |= FD_CLOEXEC; 00103 00104 if (::fcntl (m_fd, F_SETFD, val) < 0) { 00105 log_error("fcntl(F_SETFD) error"); 00106 goto done; 00107 } 00108 DL((PIDFLOCK,"CLOSE-ON-EXEC is set on FD.\n")); 00109 00110 done: 00111 if (get_error () != 0) { 00112 ::close (m_fd); 00113 m_fd = -1; 00114 } 00115 return m_error == 0 ? true : false; 00116 00117 #endif // !def WIN32 00118 }
|
|
Lock the entire file.
Definition at line 178 of file PidFileLock.cpp. References DL, m_fd, ASSA::PIDFLOCK, and trace_with_mask. Referenced by open_pid_file(), and write_pid(). 00179 { 00180 trace_with_mask ("PidFileLock::lock_region", PIDFLOCK); 00181 int ret; 00182 00183 #if defined (WIN32) 00184 return 0; 00185 #else 00186 00187 #ifdef __CYGWIN__ 00188 this->l_type = F_RDLCK; // shared lock 00189 #else 00190 this->l_type = F_WRLCK; 00191 #endif 00192 00193 this->l_start = 0; 00194 this->l_whence = SEEK_SET; 00195 this->l_len = 0; 00196 00197 ret = ::fcntl (m_fd, F_SETLK, static_cast<struct flock*>(this)); 00198 00199 DL((PIDFLOCK,"fcntl(fd=%d, F_SETLK, %s) returned: %d\n", 00200 m_fd, 00201 (this->l_type == F_RDLCK ? "F_RDLCK" : "F_WRLCK"), 00202 ret)); 00203 00204 return (ret); 00205 00206 #endif // !def WIN32 00207 }
|
|
Lock the entire file (only under Cygwin).
Definition at line 212 of file PidFileLock.cpp. References DL, m_fd, ASSA::PIDFLOCK, and trace_with_mask. Referenced by get_lock_status(), and write_pid(). 00213 { 00214 trace_with_mask ("PidFileLock::lock_region_exclusive", PIDFLOCK); 00215 int ret = 0; 00216 00217 #if defined (WIN32) 00218 return 0; 00219 #else 00220 00221 #ifdef __CYGWIN__ 00222 this->l_type = F_WRLCK; // exclusive lock - read would fail 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_WRLCK) returned: %d\n", m_fd, ret)); 00230 #endif 00231 00232 return (ret); 00233 00234 #endif // !def WIN32 00235 }
|
|
Log an error message to the log file and set internal error to errno.
Definition at line 421 of file PidFileLock.cpp. References ASSA::ASSAERR, EL, and m_error. Referenced by lock(), and open_pid_file(). 00422 { 00423 m_error = errno; 00424 EL((ASSAERR, 00425 "Error: \"Failed to get a lock on PID file - %s\".\n", msg_)); 00426 }
|
|
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 435 of file PidFileLock.cpp. References lock_region(), log_error(), m_error, m_fd, ASSA::PIDFLOCK, test_region(), and trace_with_mask. Referenced by lock(). 00436 { 00437 trace_with_mask("PidFileLock::open_pid_file", PIDFLOCK); 00438 00439 #if !defined (WIN32) 00440 00441 m_fd = ::open (fname_.c_str (), O_WRONLY|O_CREAT, 0644); 00442 if (m_fd < 0) { 00443 log_error("open() error."); 00444 return -1; 00445 } 00446 00451 pid_t owner_pid; 00452 if ((owner_pid = test_region ()) > 0) { 00453 log_error ("PID file is already locked (by someone)."); 00454 m_error = EPERM; 00455 return -1; 00456 } 00457 00460 if (lock_region () < 0) { 00461 if (errno == EACCES || errno == EAGAIN) { 00462 log_error("PID file is locked by another process"); 00463 } 00464 else { 00465 log_error("write lock error"); 00466 } 00467 return -1; 00468 } 00469 00470 #endif // !def WIN32 00471 00472 return 0; 00473 }
|
|
Test if file is unlocked.
Definition at line 355 of file PidFileLock.cpp. References DL, get_lock_status(), ASSA::PIDFLOCK, and trace_with_mask. Referenced by dump(), and open_pid_file(). 00356 { 00357 trace_with_mask ("PidFileLock::test_region", PIDFLOCK); 00358 int ret; 00359 00360 #if defined (WIN32) 00361 return 0; 00362 #else 00363 00364 ret = get_lock_status (); 00365 00366 if (ret < 0) { 00367 DL((PIDFLOCK,"Failed to retrieve lock status.\n")); 00368 return 1; 00369 } 00370 if (this->l_type == F_UNLCK) { 00371 DL((PIDFLOCK,"Region is not locked.\n")); 00372 return(0); 00373 } 00374 00375 DL((PIDFLOCK,"Region is already locked by PID %d\n", this->l_pid)); 00376 return (this->l_pid); 00377 00378 #endif // !def WIN32 00379 }
|
|
Unlock the entire file.
Definition at line 239 of file PidFileLock.cpp. References DL, m_fd, ASSA::PIDFLOCK, and trace_with_mask. Referenced by get_lock_status(), write_pid(), and ~PidFileLock(). 00240 { 00241 trace_with_mask ("PidFileLock::unlock_region", PIDFLOCK); 00242 int ret; 00243 00244 #if defined (WIN32) 00245 return 0; 00246 #else 00247 00248 this->l_type = F_UNLCK; 00249 this->l_start = 0; 00250 this->l_whence = SEEK_SET; 00251 this->l_len = 0; 00252 00253 ret = ::fcntl (m_fd, F_SETLK, static_cast<struct flock*>(this)); 00254 00255 DL((PIDFLOCK,"fcntl(fd=%d, F_SETLK, F_UNLCK) returned: %d\n", 00256 m_fd, ret)); 00257 00258 return (ret); 00259 00260 #endif // !def WIN32 00261 }
|
|
Write our process pid to the lock file.
Definition at line 132 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(). 00133 { 00134 trace_with_mask ("PidFileLock::write_pid", PIDFLOCK); 00135 00136 #if defined (WIN32) 00137 return 0; 00138 #else 00139 std::ostringstream mypid; 00140 size_t len; 00141 00142 this->l_pid = getpid (); 00143 mypid << this->l_pid << std::ends; 00144 len = strlen (mypid.str ().c_str ()); 00145 00146 #ifdef __CYGWIN__ 00147 00148 unlock_region (); // remove shared (weak) lock 00149 lock_region_exclusive (); 00150 00151 if (write (m_fd, mypid.str ().c_str (), len) != len) { 00152 return -1; 00153 } 00154 DL((PIDFLOCK,"Wrote PID=%d to the lock file.\n", l_pid)); 00155 unlock_region (); // give up the exclusive lock 00156 lock_region (); // place shared (weak) lock 00157 00158 #else // POSIX-compliant locks 00159 00160 if (write (m_fd, mypid.str ().c_str (), len) != len) { 00161 return -1; 00162 } 00163 DL((PIDFLOCK,"Wrote PID=%d to the lock file.\n", this->l_pid)); 00164 00165 #endif 00166 return 0; 00167 00168 #endif // !def WIN32 00169 }
|
|
Last system call error.
Definition at line 126 of file PidFileLock.h. Referenced by get_error(), lock(), log_error(), and open_pid_file(). |
|
Error explanation.
Definition at line 129 of file PidFileLock.h. Referenced by get_error_msg(). |
|
Lock file descriptor.
Definition at line 123 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 120 of file PidFileLock.h. Referenced by dump(), lock(), and ~PidFileLock(). |