Module: check_mk
Branch: master
Commit: d65c0a577722552019482271dbc1cdacc94b16f7
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=d65c0a57772255…
Author: Mathias Kettner <mk(a)mathias-kettner.de>
Date: Tue Feb 26 15:53:44 2013 +0100
FIX: fix user database corruption in case of a race condition
Conflicts:
ChangeLog
---
ChangeLog | 1 +
web/htdocs/userdb.py | 46 +++++++++++++++++++++-------------------------
2 files changed, 22 insertions(+), 25 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 5f4185e..d0e730d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -70,6 +70,7 @@
* FIX: fixed focus bug in transform valuespec class
* FIX: stop doing snapin refreshes after they have been removed
* FIX: sidebar snapins which refresh do not register for restart detection anymore
+ * FIX: fix user database corruption in case of a race condition
* Changed sidebar snapin reload to a global interval (option:
sidebar_update_interval), defaults to 30 seconds
* Sidebar snapins are now bulk updated with one HTTP request each interval
diff --git a/web/htdocs/userdb.py b/web/htdocs/userdb.py
index 8c3096c..075a467 100644
--- a/web/htdocs/userdb.py
+++ b/web/htdocs/userdb.py
@@ -140,22 +140,27 @@ def reset_user_attributes():
user_attributes = {}
def load_users():
- # First load monitoring contacts from Check_MK's world
filename = root_dir + "contacts.mk"
- if os.path.exists(filename):
- try:
- vars = { "contacts" : {} }
- execfile(filename, vars, vars)
- contacts = vars["contacts"]
- except Exception, e:
- if config.debug:
- raise MKGeneralException(_("Cannot read configuration file %s:
%s" %
- (filename, e)))
- else:
- html.log('load_users: Problem while loading contacts (%s - %s).
'
- 'Initializing structure...' % (filename, e))
- contacts = {}
- else:
+
+ # Make sure that the file exists without modifying it, *if* it exists.
+ # Note the lock will be released at end of page request automatically.
+ file(filename, "a")
+ aquire_lock(filename)
+
+ # First load monitoring contacts from Check_MK's world. If this is
+ # the first time, then the file will be empty, which is no problem.
+ # Execfile will the simply leave contacts = {} unchanged.
+ try:
+ vars = { "contacts" : {} }
+ execfile(filename, vars, vars)
+ contacts = vars["contacts"]
+ except Exception, e:
+ if config.debug:
+ raise MKGeneralException(_("Cannot read configuration file %s: %s"
%
+ (filename, e)))
+ else:
+ html.log('load_users: Problem while loading contacts (%s - %s). '
+ 'Initializing structure...' % (filename, e))
contacts = {}
# Now add information about users from the Web world
@@ -261,6 +266,7 @@ def load_users():
def split_dict(d, keylist, positive):
return dict([(k,v) for (k,v) in d.items() if (k in keylist) == positive])
+
def save_users(profiles):
custom_values = user_attributes.keys()
@@ -300,19 +306,9 @@ def save_users(profiles):
if p in multisite_keys +
multisite_attributes(profile.get('connector'))])
filename = root_dir + "contacts.mk"
- locked = False
- if os.path.exists(filename):
- # When the file exists, lock the file before opening (and truncating) it
- aquire_lock(filename)
- locked = True
# Check_MK's monitoring contacts
out = create_user_file(filename, "w")
-
- # In create mode lock the file after creation
- if not locked:
- aquire_lock(filename)
-
out.write("# Written by Multisite UserDB\n# encoding: utf-8\n\n")
out.write("contacts.update(\n%s\n)\n" % pprint.pformat(contacts))
out.close()