Blame SOURCES/firewalld-0.3.9-RHBZ#1161745.patch

3d17f4
Adapted version of
3d17f4
 
3d17f4
commit b3b451d6f8946986b8f50c8bcddeef50ed7a5f8f
3d17f4
Author: Jiri Popelka <jpopelka@redhat.com>
3d17f4
Date:   Mon Oct 27 17:45:46 2014 +0100
3d17f4
3d17f4
    ipXtables: use -w or -w2 if supported
3d17f4
    
3d17f4
    iptables (since 1.4.20) has a locking mechanism [1],
3d17f4
    which prevents multiple instances of the program from running concurrently.
3d17f4
    
3d17f4
    It can happen that some other daemon (libvirtd [2], docker [3])
3d17f4
    is calling iptables at the same time as firewalld.
3d17f4
    In that case the second one which calls iptables fails with:
3d17f4
    "Another app is currently holding the xtables lock.
3d17f4
    Perhaps you want to use the -w option?"
3d17f4
    
3d17f4
    The easiest work-around is the use the suggested "-w" option,
3d17f4
    which makes the second iptables instance wait till the lock is released.
3d17f4
    Even better is to use "-w2" [2] which makes it wait for max 2 seconds.
3d17f4
    
3d17f4
    [1] https://git.netfilter.org/iptables/commit/?id=93587a04d0f2511e108bbc4d87a8b9d28a5c5dd8
3d17f4
    [2] https://bugzilla.redhat.com/show_bug.cgi?id=1098281
3d17f4
    [3] https://bugzilla.redhat.com/show_bug.cgi?id=1151067
3d17f4
    [4] https://git.netfilter.org/iptables/commit/?id=aaa4ace72ba1d195bbf436134a336816c33f7bd0
3d17f4
3d17f4
diff --git a/src/firewall/core/ipXtables.py b/src/firewall/core/ipXtables.py
3d17f4
index 8f61bb8..e8381f2 100644
3d17f4
--- a/src/firewall/core/ipXtables.py
3d17f4
+++ b/src/firewall/core/ipXtables.py
3d17f4
@@ -125,10 +125,14 @@ class ip4tables:
3d17f4
 
3d17f4
     def __init__(self):
3d17f4
         self._command = COMMAND[self.ipv]
3d17f4
+        self.wait_option = self._detect_wait_option()
3d17f4
 
3d17f4
     def __run(self, args):
3d17f4
         # convert to string list
3d17f4
-        _args = ["%s" % item for item in args]
3d17f4
+        if self.wait_option:
3d17f4
+            _args = [self.wait_option] + ["%s" % item for item in args]
3d17f4
+        else:
3d17f4
+            _args = ["%s" % item for item in args]
3d17f4
         log.debug2("%s: %s %s", self.__class__, self._command, " ".join(_args))
3d17f4
         (status, ret) = runProg(self._command, _args)
3d17f4
         if status != 0:
3d17f4
@@ -170,6 +174,18 @@ class ip4tables:
3d17f4
 
3d17f4
         return tables
3d17f4
 
3d17f4
+    def _detect_wait_option(self):
3d17f4
+        wait_option = ""
3d17f4
+        (status, ret) = runProg(self._command, ["-w", "-L"])  # since iptables-1.4.20
3d17f4
+        if status == 0:
3d17f4
+            wait_option = "-w"  # wait for xtables lock
3d17f4
+            (status, ret) = runProg(self._command, ["-w2", "-L"])  # since iptables > 1.4.21
3d17f4
+            if status == 0:
3d17f4
+                wait_option = "-w2"  # wait max 2 seconds
3d17f4
+            log.debug2("%s: %s will be using %s option.", self.__class__, self._command, wait_option)
3d17f4
+
3d17f4
+        return wait_option
3d17f4
+
3d17f4
     def flush(self):
3d17f4
         tables = self.used_tables()
3d17f4
         for table in tables: