Revision b6522276
b/lib/errors.py | ||
---|---|---|
82 | 82 |
pass |
83 | 83 |
|
84 | 84 |
|
85 |
class PidFileLockError(LockError): |
|
86 |
"""PID file is already locked by another process. |
|
87 |
|
|
88 |
""" |
|
89 |
|
|
90 |
|
|
85 | 91 |
class HypervisorError(GenericError): |
86 | 92 |
"""Hypervisor-related exception. |
87 | 93 |
|
b/lib/utils/io.py | ||
---|---|---|
701 | 701 |
logging.exception("Can't read pid file") |
702 | 702 |
return 0 |
703 | 703 |
|
704 |
return _ParsePidFileContents(raw_data) |
|
705 |
|
|
706 |
|
|
707 |
def _ParsePidFileContents(data): |
|
708 |
"""Tries to extract a process ID from a PID file's content. |
|
709 |
|
|
710 |
@type data: string |
|
711 |
@rtype: int |
|
712 |
@return: Zero if nothing could be read, PID otherwise |
|
713 |
|
|
714 |
""" |
|
704 | 715 |
try: |
705 |
pid = int(raw_data)
|
|
706 |
except (TypeError, ValueError), err:
|
|
716 |
pid = int(data) |
|
717 |
except (TypeError, ValueError): |
|
707 | 718 |
logging.info("Can't parse pid file contents", exc_info=True) |
708 | 719 |
return 0 |
709 |
|
|
710 |
return pid |
|
720 |
else: |
|
721 |
return pid
|
|
711 | 722 |
|
712 | 723 |
|
713 | 724 |
def ReadLockedPidFile(path): |
... | ... | |
834 | 845 |
""" |
835 | 846 |
# We don't rename nor truncate the file to not drop locks under |
836 | 847 |
# existing processes |
837 |
fd_pidfile = os.open(pidfile, os.O_WRONLY | os.O_CREAT, 0600)
|
|
848 |
fd_pidfile = os.open(pidfile, os.O_RDWR | os.O_CREAT, 0600)
|
|
838 | 849 |
|
839 | 850 |
# Lock the PID file (and fail if not possible to do so). Any code |
840 | 851 |
# wanting to send a signal to the daemon should try to lock the PID |
841 | 852 |
# file before reading it. If acquiring the lock succeeds, the daemon is |
842 | 853 |
# no longer running and the signal should not be sent. |
843 |
filelock.LockFile(fd_pidfile) |
|
854 |
try: |
|
855 |
filelock.LockFile(fd_pidfile) |
|
856 |
except errors.LockError: |
|
857 |
msg = ["PID file '%s' is already locked by another process" % pidfile] |
|
858 |
# Try to read PID file |
|
859 |
pid = _ParsePidFileContents(os.read(fd_pidfile, 100)) |
|
860 |
if pid > 0: |
|
861 |
msg.append(", PID read from file is %s" % pid) |
|
862 |
raise errors.PidFileLockError("".join(msg)) |
|
844 | 863 |
|
845 | 864 |
os.write(fd_pidfile, "%d\n" % os.getpid()) |
846 | 865 |
|
b/test/ganeti.utils.io_unittest.py | ||
---|---|---|
711 | 711 |
read_pid = utils.ReadPidFile(pid_file) |
712 | 712 |
self.failUnlessEqual(read_pid, os.getpid()) |
713 | 713 |
self.failUnless(utils.IsProcessAlive(read_pid)) |
714 |
self.failUnlessRaises(errors.LockError, utils.WritePidFile, |
|
714 |
self.failUnlessRaises(errors.PidFileLockError, utils.WritePidFile,
|
|
715 | 715 |
self.f_dpn('test')) |
716 | 716 |
os.close(fd) |
717 | 717 |
utils.RemoveFile(self.f_dpn("test")) |
... | ... | |
747 | 747 |
read_pid = utils.ReadPidFile(pid_file) |
748 | 748 |
self.failUnlessEqual(read_pid, new_pid) |
749 | 749 |
self.failUnless(utils.IsProcessAlive(new_pid)) |
750 |
|
|
751 |
# Try writing to locked file |
|
752 |
try: |
|
753 |
utils.WritePidFile(pid_file) |
|
754 |
except errors.PidFileLockError, err: |
|
755 |
errmsg = str(err) |
|
756 |
self.assertTrue(errmsg.endswith(" %s" % new_pid), |
|
757 |
msg=("Error message ('%s') didn't contain correct" |
|
758 |
" PID (%s)" % (errmsg, new_pid))) |
|
759 |
else: |
|
760 |
self.fail("Writing to locked file didn't fail") |
|
761 |
|
|
750 | 762 |
utils.KillProcess(new_pid, waitpid=True) |
751 | 763 |
self.failIf(utils.IsProcessAlive(new_pid)) |
752 | 764 |
utils.RemoveFile(self.f_dpn('child')) |
753 | 765 |
self.failUnlessRaises(errors.ProgrammerError, utils.KillProcess, 0) |
754 | 766 |
|
767 |
def testExceptionType(self): |
|
768 |
# Make sure the PID lock error is a subclass of LockError in case some code |
|
769 |
# depends on it |
|
770 |
self.assertTrue(issubclass(errors.PidFileLockError, errors.LockError)) |
|
771 |
|
|
755 | 772 |
def tearDown(self): |
756 | 773 |
shutil.rmtree(self.dir) |
757 | 774 |
|
Also available in: Unified diff