Merge pull request #151 from YunoHost/enh-simpler-lock-system

[enh] Simpler lock system
This commit is contained in:
Laurent Peuch 2017-08-18 04:12:56 +02:00 committed by GitHub
commit dfcfecc84a
4 changed files with 36 additions and 19 deletions

3
debian/control vendored
View file

@ -15,7 +15,8 @@ Depends: ${misc:Depends}, ${python:Depends},
python-bottle (>= 0.12), python-bottle (>= 0.12),
python-gnupg, python-gnupg,
python-gevent-websocket, python-gevent-websocket,
python-argcomplete python-argcomplete,
python-psutil
Replaces: yunohost-cli Replaces: yunohost-cli
Breaks: yunohost-cli Breaks: yunohost-cli
Description: prototype interfaces with ease in Python Description: prototype interfaces with ease in Python

View file

@ -5,6 +5,7 @@ import time
import json import json
import errno import errno
import logging import logging
import psutil
from importlib import import_module from importlib import import_module
@ -429,7 +430,6 @@ class MoulinetteLock(object):
self._lockfile = '/var/run/moulinette_%s.lock' % namespace self._lockfile = '/var/run/moulinette_%s.lock' % namespace
self._stale_checked = False self._stale_checked = False
self._locked = False self._locked = False
self._bypass = False
def acquire(self): def acquire(self):
"""Attempt to acquire the lock for the moulinette instance """Attempt to acquire the lock for the moulinette instance
@ -442,17 +442,13 @@ class MoulinetteLock(object):
start_time = time.time() start_time = time.time()
while True: while True:
if 'BYPASS_LOCK' in os.environ and os.environ['BYPASS_LOCK'] == 'yes': lock_pid = self._lock_PID()
self._bypass = True
break
if not os.path.isfile(self._lockfile): if lock_pid is None:
self._lock() self._lock()
break break
elif not self._stale_checked: elif not self._stale_checked:
self._stale_checked = True self._stale_checked = True
with open(self._lockfile) as f:
lock_pid = f.read().strip()
# Delete stale lock file # Delete stale lock file
if not lock_pid or not os.path.exists( if not lock_pid or not os.path.exists(
os.path.join('/proc', lock_pid, 'exe')): os.path.join('/proc', lock_pid, 'exe')):
@ -476,9 +472,7 @@ class MoulinetteLock(object):
""" """
if self._locked: if self._locked:
if not self._bypass: os.unlink(self._lockfile)
os.unlink(self._lockfile)
logger.debug('lock has been released') logger.debug('lock has been released')
self._locked = False self._locked = False
@ -492,8 +486,37 @@ class MoulinetteLock(object):
moulinette.m18n.g('permission_denied'), moulinette.m18n.g('permission_denied'),
moulinette.m18n.g('root_required'))) moulinette.m18n.g('root_required')))
def _lock_PID(self):
if not os.path.isfile(self._lockfile):
return None
with open(self._lockfile) as f:
lock_pid = f.read().strip()
return lock_pid
def _is_son_of_locked(self):
lock_pid = self._lock_PID()
if lock_pid is None:
return False
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
# with the lock...
if parent.ppid() == int(lock_pid):
return True
# Otherwise, try 'next' parent
parent = parent.parent()
return False
def __enter__(self): def __enter__(self):
if not self._locked: if not self._locked and not self._is_son_of_locked():
self.acquire() self.acquire()
return self return self

View file

@ -152,10 +152,6 @@ class BaseActionsMapParser(object):
namespace = argparse.Namespace() namespace = argparse.Namespace()
namespace._tid = tid namespace._tid = tid
# Check lock
if not self.get_conf(tid, 'lock'):
os.environ['BYPASS_LOCK'] = 'yes'
# Perform authentication if needed # Perform authentication if needed
if self.get_conf(tid, 'authenticate'): if self.get_conf(tid, 'authenticate'):
auth_conf, cls = self.get_conf(tid, 'authenticator') auth_conf, cls = self.get_conf(tid, 'authenticator')

View file

@ -634,9 +634,6 @@ class ActionsMapParser(BaseActionsMapParser):
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log')) raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
ret = argparse.Namespace() ret = argparse.Namespace()
if not self.get_conf(tid, 'lock'):
os.environ['BYPASS_LOCK'] = 'yes'
# Perform authentication if needed # Perform authentication if needed
if self.get_conf(tid, 'authenticate'): if self.get_conf(tid, 'authenticate'):
# TODO: Clean this hard fix and find a way to set an authenticator # TODO: Clean this hard fix and find a way to set an authenticator