Commit b6522276 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files Improve error reporting

If the PID file is already locked by another process, try to read
the content and report it as part of the error message.
Signed-off-by: default avatarMichael Hanselmann <>
Reviewed-by: default avatarIustin Pop <>
parent 2dbc6857
......@@ -82,6 +82,12 @@ class LockError(GenericError):
class PidFileLockError(LockError):
"""PID file is already locked by another process.
class HypervisorError(GenericError):
"""Hypervisor-related exception.
......@@ -701,13 +701,24 @@ def ReadPidFile(pidfile):
logging.exception("Can't read pid file")
return 0
return _ParsePidFileContents(raw_data)
def _ParsePidFileContents(data):
"""Tries to extract a process ID from a PID file's content.
@type data: string
@rtype: int
@return: Zero if nothing could be read, PID otherwise
pid = int(raw_data)
except (TypeError, ValueError), err:
pid = int(data)
except (TypeError, ValueError):"Can't parse pid file contents", exc_info=True)
return 0
return pid
return pid
def ReadLockedPidFile(path):
......@@ -834,13 +845,21 @@ def WritePidFile(pidfile):
# We don't rename nor truncate the file to not drop locks under
# existing processes
fd_pidfile =, os.O_WRONLY | os.O_CREAT, 0600)
fd_pidfile =, os.O_RDWR | os.O_CREAT, 0600)
# Lock the PID file (and fail if not possible to do so). Any code
# wanting to send a signal to the daemon should try to lock the PID
# file before reading it. If acquiring the lock succeeds, the daemon is
# no longer running and the signal should not be sent.
except errors.LockError:
msg = ["PID file '%s' is already locked by another process" % pidfile]
# Try to read PID file
pid = _ParsePidFileContents(, 100))
if pid > 0:
msg.append(", PID read from file is %s" % pid)
raise errors.PidFileLockError("".join(msg))
os.write(fd_pidfile, "%d\n" % os.getpid())
......@@ -711,7 +711,7 @@ class TestPidFileFunctions(unittest.TestCase):
read_pid = utils.ReadPidFile(pid_file)
self.failUnlessEqual(read_pid, os.getpid())
self.failUnlessRaises(errors.LockError, utils.WritePidFile,
self.failUnlessRaises(errors.PidFileLockError, utils.WritePidFile,
......@@ -747,11 +747,28 @@ class TestPidFileFunctions(unittest.TestCase):
read_pid = utils.ReadPidFile(pid_file)
self.failUnlessEqual(read_pid, new_pid)
# Try writing to locked file
except errors.PidFileLockError, err:
errmsg = str(err)
self.assertTrue(errmsg.endswith(" %s" % new_pid),
msg=("Error message ('%s') didn't contain correct"
" PID (%s)" % (errmsg, new_pid)))
else:"Writing to locked file didn't fail")
utils.KillProcess(new_pid, waitpid=True)
self.failUnlessRaises(errors.ProgrammerError, utils.KillProcess, 0)
def testExceptionType(self):
# Make sure the PID lock error is a subclass of LockError in case some code
# depends on it
self.assertTrue(issubclass(errors.PidFileLockError, errors.LockError))
def tearDown(self):
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment