Allow to give lock to multiple processes (#154)

* Check also son_of_locked for self
* Check again that we're son of locked when trying to acquire lock
* Support having multiple PIDs in lock file..
* Fix/improve son_of_lock detection
This commit is contained in:
Alexandre Aubin 2017-10-08 23:49:21 +02:00 committed by GitHub
parent ca580bbcfb
commit 0665cb4dd5

View file

@ -442,16 +442,21 @@ class MoulinetteLock(object):
start_time = time.time()
while True:
lock_pid = self._lock_PID()
if lock_pid is None:
lock_pids = self._lock_PIDs()
if self._is_son_of(lock_pids):
return
if lock_pids == []:
self._lock()
break
elif not self._stale_checked:
self._stale_checked = True
# Delete stale lock file
if not lock_pid or not os.path.exists(
os.path.join('/proc', lock_pid, 'exe')):
# Check locked process still exist and take lock if it doesnt
# FIXME : what do in the context of multiple locks :|
first_lock = lock_pids[0]
if not os.path.exists(os.path.join('/proc', str(first_lock), 'exe')):
logger.debug('stale lock file found')
self._lock()
break
@ -486,28 +491,32 @@ class MoulinetteLock(object):
moulinette.m18n.g('permission_denied'),
moulinette.m18n.g('root_required')))
def _lock_PID(self):
def _lock_PIDs(self):
if not os.path.isfile(self._lockfile):
return None
return []
with open(self._lockfile) as f:
lock_pid = f.read().strip()
lock_pids = f.read().strip().split('\n')
return lock_pid
# Make sure to convert those pids to integers
lock_pids = [ int(pid) for pid in lock_pids ]
def _is_son_of_locked(self):
lock_pid = self._lock_PID()
return lock_pids
if lock_pid is None:
def _is_son_of(self, lock_pids):
if lock_pids == []:
return False
# Start with self
parent = psutil.Process()
# While this is not the very first process
while parent.parent() is not None:
# If parent PID is the lock, the yes! we are a son of the process
# While there is a parent... (e.g. init has no parent)
while parent is not None:
# If parent PID is the lock, then yes! we are a son of the process
# with the lock...
if parent.ppid() == int(lock_pid):
if parent.pid in lock_pids:
return True
# Otherwise, try 'next' parent
parent = parent.parent()
@ -515,7 +524,7 @@ class MoulinetteLock(object):
return False
def __enter__(self):
if not self._locked and not self._is_son_of_locked():
if not self._locked:
self.acquire()
return self