Make pid file locking non-blocking

fcntl.flock will block indefinitely if another process holds an exclusive
lock. A non-blocking flock operation will raise an error when a lock already
exists so we can fail immediately.

Closes-bug: 1315507
Change-Id: Icf97b1f8643157719b3d28ac2c0c1576a5069697
This commit is contained in:
Ryan Moe 2014-05-02 13:08:45 -07:00
parent 52dc25bf41
commit 797fa55fef
2 changed files with 9 additions and 9 deletions

View File

@ -29,16 +29,15 @@ LOG = logging.getLogger(__name__)
class Pidfile(object):
def __init__(self, pidfile, procname, uuid=None):
try:
self.fd = os.open(pidfile, os.O_CREAT | os.O_RDWR)
except IOError:
LOG.exception(_("Failed to open pidfile: %s"), pidfile)
sys.exit(1)
self.pidfile = pidfile
self.procname = procname
self.uuid = uuid
if not not fcntl.flock(self.fd, fcntl.LOCK_EX):
raise IOError(_('Unable to lock pid file'))
try:
self.fd = os.open(pidfile, os.O_CREAT | os.O_RDWR)
fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
LOG.exception(_("Error while handling pidfile: %s"), pidfile)
sys.exit(1)
def __str__(self):
return self.pidfile

View File

@ -44,7 +44,8 @@ class TestPidfile(base.BaseTestCase):
daemon.Pidfile('thefile', 'python')
self.os.open.assert_called_once_with('thefile', os.O_CREAT | os.O_RDWR)
self.fcntl.flock.assert_called_once_with(FAKE_FD, self.fcntl.LOCK_EX)
self.fcntl.flock.assert_called_once_with(FAKE_FD, self.fcntl.LOCK_EX |
self.fcntl.LOCK_NB)
def test_init_open_fail(self):
self.os.open.side_effect = IOError
@ -61,7 +62,7 @@ class TestPidfile(base.BaseTestCase):
p = daemon.Pidfile('thefile', 'python')
p.unlock()
self.fcntl.flock.assert_has_calls([
mock.call(FAKE_FD, self.fcntl.LOCK_EX),
mock.call(FAKE_FD, self.fcntl.LOCK_EX | self.fcntl.LOCK_NB),
mock.call(FAKE_FD, self.fcntl.LOCK_UN)]
)