|
|
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:
|