From 9006f8980f13e11a9ad7691e5cfa87b7ca094355 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 13 Aug 2017 16:22:58 -0400 Subject: [PATCH 1/4] [enh] Check if parent already has lock --- moulinette/core.py | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/moulinette/core.py b/moulinette/core.py index 9a42a2a7..1981ae7b 100644 --- a/moulinette/core.py +++ b/moulinette/core.py @@ -5,6 +5,7 @@ import time import json import errno import logging +import psutil from importlib import import_module @@ -446,13 +447,13 @@ class MoulinetteLock(object): self._bypass = True break - if not os.path.isfile(self._lockfile): + lock_pid = self._lock_PID() + + if lock_pid is None: self._lock() break elif not self._stale_checked: self._stale_checked = True - with open(self._lockfile) as f: - lock_pid = f.read().strip() # Delete stale lock file if not lock_pid or not os.path.exists( os.path.join('/proc', lock_pid, 'exe')): @@ -492,8 +493,38 @@ class MoulinetteLock(object): moulinette.m18n.g('permission_denied'), 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() != 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): - if not self._locked: + if not self._locked and not self._is_son_of_locked(): self.acquire() return self From ab47f30f1845ba3bb036eb814d7214fa5f13c82b Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 13 Aug 2017 16:40:44 -0400 Subject: [PATCH 2/4] Forget about the old BYPASS_LOCK thing from actionmap --- moulinette/core.py | 9 +-------- moulinette/interfaces/__init__.py | 4 ---- moulinette/interfaces/api.py | 3 --- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/moulinette/core.py b/moulinette/core.py index 1981ae7b..5b52e1a6 100644 --- a/moulinette/core.py +++ b/moulinette/core.py @@ -430,7 +430,6 @@ class MoulinetteLock(object): self._lockfile = '/var/run/moulinette_%s.lock' % namespace self._stale_checked = False self._locked = False - self._bypass = False def acquire(self): """Attempt to acquire the lock for the moulinette instance @@ -443,10 +442,6 @@ class MoulinetteLock(object): start_time = time.time() while True: - if 'BYPASS_LOCK' in os.environ and os.environ['BYPASS_LOCK'] == 'yes': - self._bypass = True - break - lock_pid = self._lock_PID() if lock_pid is None: @@ -477,9 +472,7 @@ class MoulinetteLock(object): """ if self._locked: - if not self._bypass: - os.unlink(self._lockfile) - + os.unlink(self._lockfile) logger.debug('lock has been released') self._locked = False diff --git a/moulinette/interfaces/__init__.py b/moulinette/interfaces/__init__.py index e3629a39..30ba8ae9 100644 --- a/moulinette/interfaces/__init__.py +++ b/moulinette/interfaces/__init__.py @@ -152,10 +152,6 @@ class BaseActionsMapParser(object): namespace = argparse.Namespace() namespace._tid = tid - # Check lock - if not self.get_conf(tid, 'lock'): - os.environ['BYPASS_LOCK'] = 'yes' - # Perform authentication if needed if self.get_conf(tid, 'authenticate'): auth_conf, cls = self.get_conf(tid, 'authenticator') diff --git a/moulinette/interfaces/api.py b/moulinette/interfaces/api.py index 0f1f653c..1c5e3d67 100644 --- a/moulinette/interfaces/api.py +++ b/moulinette/interfaces/api.py @@ -634,9 +634,6 @@ class ActionsMapParser(BaseActionsMapParser): raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log')) ret = argparse.Namespace() - if not self.get_conf(tid, 'lock'): - os.environ['BYPASS_LOCK'] = 'yes' - # Perform authentication if needed if self.get_conf(tid, 'authenticate'): # TODO: Clean this hard fix and find a way to set an authenticator From 869a4e2f14330c82fb7508409e744edcbb3018ef Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 13 Aug 2017 16:58:52 -0400 Subject: [PATCH 3/4] Add dependency to python-psutil --- debian/control | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 4783433c..476f0f0c 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,8 @@ Depends: ${misc:Depends}, ${python:Depends}, python-bottle (>= 0.12), python-gnupg, python-gevent-websocket, - python-argcomplete + python-argcomplete, + python-psutil Replaces: yunohost-cli Breaks: yunohost-cli Description: prototype interfaces with ease in Python From d28990350c238d98372e0dc1d96fd6685ec7838c Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 13 Aug 2017 17:18:17 -0400 Subject: [PATCH 4/4] pep8 <3 --- moulinette/core.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/moulinette/core.py b/moulinette/core.py index 5b52e1a6..52595f80 100644 --- a/moulinette/core.py +++ b/moulinette/core.py @@ -496,7 +496,6 @@ class MoulinetteLock(object): return lock_pid - def _is_son_of_locked(self): lock_pid = self._lock_PID() @@ -506,7 +505,7 @@ class MoulinetteLock(object): parent = psutil.Process() # While this is not the very first process - while parent.parent() != None: + 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):