From 8728007d1ef5090c4b7f0cc4d9f9e7c95a98537e Mon Sep 17 00:00:00 2001 From: Jarrod Johnon Date: Tue, 23 Sep 2014 12:08:13 -0400 Subject: [PATCH] Fix DB corruption potential Make sure that the dbm object is closed before another thread might come along. Out of an overabundance of caution, also join() existing cfgwriter thread to make sure that only one thread touches it at a time. In theory, it should only possibly be after the db is closed, but take no chances. --- .../confluent/config/configmanager.py | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/confluent_server/confluent/config/configmanager.py b/confluent_server/confluent/config/configmanager.py index b98565dd..ec438894 100644 --- a/confluent_server/confluent/config/configmanager.py +++ b/confluent_server/confluent/config/configmanager.py @@ -1130,6 +1130,9 @@ class ConfigManager(object): cls._writepending = True return cls._syncrunning = True + # if the thread is exiting, join it to let it close, just in case + if cls._cfgwriter is not None: + cls._cfgwriter.join() cls._cfgwriter = threading.Thread(target=cls._sync_to_file) cls._cfgwriter.start() @@ -1141,14 +1144,16 @@ class ConfigManager(object): del _cfgstore['dirtyglobals'] _mkpath(cls._cfgdir) globalf = dbm.open(cls._cfgdir + "/globals", 'c', 384) # 0600 - for globalkey in dirtyglobals: - if globalkey in _cfgstore['globals']: - globalf[globalkey] = \ - cPickle.dumps(_cfgstore['globals'][globalkey]) - else: - if globalkey in globalf: - del globalf[globalkey] - globalf.close() + try: + for globalkey in dirtyglobals: + if globalkey in _cfgstore['globals']: + globalf[globalkey] = \ + cPickle.dumps(_cfgstore['globals'][globalkey]) + else: + if globalkey in globalf: + del globalf[globalkey] + finally: + globalf.close() if 'dirtykeys' in _cfgstore: with _dirtylock: currdirt = copy.deepcopy(_cfgstore['dirtykeys']) @@ -1163,13 +1168,16 @@ class ConfigManager(object): currdict = _cfgstore['tenant'][tenant] for category in dkdict.iterkeys(): _mkpath(pathname) - dbf = dbm.open(pathname + category, 'c', 384) # 0600 mode - for ck in dkdict[category]: - if ck not in currdict[category]: - if ck in dbf: - del dbf[ck] - else: - dbf[ck] = cPickle.dumps(currdict[category][ck]) + dbf = dbm.open(pathname + category, 'c', 384): # 0600 + try: + for ck in dkdict[category]: + if ck not in currdict[category]: + if ck in dbf: + del dbf[ck] + else: + dbf[ck] = cPickle.dumps(currdict[category][ck]) + finally: + dbf.close() willrun = False with cls._syncstate: if cls._writepending: