Module: check_mk
Branch: master
Commit: e1e8b8ae5b019607d721598db9b6a821d65aae31
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=e1e8b8ae5b0196…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Tue Jun 27 10:24:37 2017 +0200
Added some non blocking locking and pid_file handling code
Change-Id: I0dc2175de6bf6a049d5425b461f47ad70ad12e6f
---
lib/daemon.py | 18 ++++++++++++++++++
lib/store.py | 19 +++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/lib/daemon.py b/lib/daemon.py
index 79ea505..b9323cf 100644
--- a/lib/daemon.py
+++ b/lib/daemon.py
@@ -31,6 +31,9 @@ from grp import getgrnam
import ctypes
import ctypes.util
+import cmk.store
+from .exceptions import MKGeneralException
+
def daemonize(user=0, group=0):
# do the UNIX double-fork magic, see Stevens' "Advanced
@@ -78,6 +81,21 @@ def daemonize(user=0, group=0):
os.close(so)
+def lock_with_pid_file(path):
+ """
+ Use this after daemonizing or in foreground mode to ensure there is only
+ one process running.
+ """
+ if not cmk.store.try_aquire_lock(path):
+ raise MKGeneralException("Failed to aquire PID file lock: "
+ "Another process is already running")
+
+ # Now that we have the lock we are allowed to write our pid to the file.
+ # The pid can then be used by the init script.
+ with file(path, "w") as f:
+ f.write("%d\n" % os.getpid())
+
+
def set_cmdline(cmdline):
"""
Change the process name and process command line on of the running process
diff --git a/lib/store.py b/lib/store.py
index 6a5b18c..b7d1013 100644
--- a/lib/store.py
+++ b/lib/store.py
@@ -240,7 +240,7 @@ def save_to_mk_file(path, key, value):
g_aquired_locks = []
g_locked_paths = []
-def aquire_lock(path):
+def aquire_lock(path, blocking=True):
if path in g_locked_paths:
return True # No recursive locking
@@ -252,7 +252,11 @@ def aquire_lock(path):
# Handle the case where the file has been renamed in the meantime
while True:
- fcntl.flock(fd, fcntl.LOCK_EX)
+ flags = fcntl.LOCK_EX
+ if not blocking:
+ flags |= fcntl.LOCK_NB
+
+ fcntl.flock(fd, flags)
fd_new = os.open(path, os.O_RDONLY | os.O_CREAT, 0660)
if os.path.sameopenfile(fd, fd_new):
os.close(fd_new)
@@ -265,6 +269,17 @@ def aquire_lock(path):
g_locked_paths.append(path)
+def try_aquire_lock(path):
+ try:
+ aquire_lock(path, blocking=False)
+ return True
+ except IOError, e:
+ if e.errno == 11: # Resource temporarily unavailable
+ return False
+ else:
+ raise
+
+
def release_lock(path):
if path not in g_locked_paths:
return # no unlocking needed