e3c68b
From f40570f2f784dc61edb061a4931dcfc16bf51e7e Mon Sep 17 00:00:00 2001
e3c68b
From: Aravinda VK <avishwan@redhat.com>
e3c68b
Date: Mon, 5 Aug 2019 19:00:21 +0530
e3c68b
Subject: [PATCH 277/284] geo-rep: Fix Config Get Race
e3c68b
e3c68b
When two threads(sync jobs) in Geo-rep worker calls `gconf.get` and
e3c68b
`gconf.getr`(realtime) at the sametime, `getr` resets the conf object
e3c68b
and other one gets None. Thread Lock is introduced to fix the issue.
e3c68b
e3c68b
```
e3c68b
  File "/usr/libexec/glusterfs/python/syncdaemon/syncdutils.py",
e3c68b
  line 368, in twrap
e3c68b
    tf(*aargs)
e3c68b
  File "/usr/libexec/glusterfs/python/syncdaemon/master.py", line 1987,
e3c68b
  in syncjob
e3c68b
    po = self.sync_engine(pb, self.log_err)
e3c68b
  File "/usr/libexec/glusterfs/python/syncdaemon/resource.py",
e3c68b
  line 1444, in rsync
e3c68b
    rconf.ssh_ctl_args + \
e3c68b
AttributeError: 'NoneType' object has no attribute 'split'
e3c68b
```
e3c68b
e3c68b
Backport of:
e3c68b
 > Patch: https://review.gluster.org/#/c/glusterfs/+/23158/
e3c68b
 > Change-Id: I9c245e5c36338265354e158f5baa32b119eb2da5
e3c68b
 > Updates: bz#1737484
e3c68b
 > Signed-off-by: Aravinda VK <avishwan@redhat.com>
e3c68b
e3c68b
Change-Id: I9c245e5c36338265354e158f5baa32b119eb2da5
e3c68b
BUG: 1729915
e3c68b
Signed-off-by: Kotresh HR <khiremat@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/178960
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
e3c68b
---
e3c68b
 geo-replication/syncdaemon/gsyncdconfig.py | 27 +++++++++++++++++++++------
e3c68b
 1 file changed, 21 insertions(+), 6 deletions(-)
e3c68b
e3c68b
diff --git a/geo-replication/syncdaemon/gsyncdconfig.py b/geo-replication/syncdaemon/gsyncdconfig.py
e3c68b
index 1fc451f..38f3594 100644
e3c68b
--- a/geo-replication/syncdaemon/gsyncdconfig.py
e3c68b
+++ b/geo-replication/syncdaemon/gsyncdconfig.py
e3c68b
@@ -17,6 +17,7 @@ import os
e3c68b
 import shutil
e3c68b
 from string import Template
e3c68b
 from datetime import datetime
e3c68b
+from threading import Lock
e3c68b
 
e3c68b
 
e3c68b
 # Global object which can be used in other modules
e3c68b
@@ -35,6 +36,7 @@ class GconfInvalidValue(Exception):
e3c68b
 class Gconf(object):
e3c68b
     def __init__(self, default_conf_file, custom_conf_file=None,
e3c68b
                  args={}, extra_tmpl_args={}, override_from_args=False):
e3c68b
+        self.lock = Lock()
e3c68b
         self.default_conf_file = default_conf_file
e3c68b
         self.custom_conf_file = custom_conf_file
e3c68b
         self.tmp_conf_file = None
e3c68b
@@ -163,6 +165,11 @@ class Gconf(object):
e3c68b
         if value is not None and not self._is_valid_value(name, value):
e3c68b
             raise GconfInvalidValue()
e3c68b
 
e3c68b
+
e3c68b
+    def _load_with_lock(self):
e3c68b
+        with self.lock:
e3c68b
+            self._load()
e3c68b
+
e3c68b
     def _load(self):
e3c68b
         self.gconf = {}
e3c68b
         self.template_conf = []
e3c68b
@@ -230,12 +237,19 @@ class Gconf(object):
e3c68b
         self._tmpl_substitute()
e3c68b
         self._do_typecast()
e3c68b
 
e3c68b
-    def reload(self):
e3c68b
+    def reload(self, with_lock=True):
e3c68b
         if self._is_config_changed():
e3c68b
-            self._load()
e3c68b
+            if with_lock:
e3c68b
+                self._load_with_lock()
e3c68b
+            else:
e3c68b
+                self._load()
e3c68b
 
e3c68b
-    def get(self, name, default_value=None):
e3c68b
-        return self.gconf.get(name, default_value)
e3c68b
+    def get(self, name, default_value=None, with_lock=True):
e3c68b
+        if with_lock:
e3c68b
+            with self.lock:
e3c68b
+                return self.gconf.get(name, default_value)
e3c68b
+        else:
e3c68b
+            return self.gconf.get(name, default_value)
e3c68b
 
e3c68b
     def getall(self, show_defaults=False, show_non_configurable=False):
e3c68b
         cnf = {}
e3c68b
@@ -276,8 +290,9 @@ class Gconf(object):
e3c68b
         return cnf
e3c68b
 
e3c68b
     def getr(self, name, default_value=None):
e3c68b
-        self.reload()
e3c68b
-        return self.get(name, default_value)
e3c68b
+        with self.lock:
e3c68b
+            self.reload(with_lock=False)
e3c68b
+            return self.get(name, default_value, with_lock=False)
e3c68b
 
e3c68b
     def get_help(self, name=None):
e3c68b
         pass
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b