summaryrefslogtreecommitdiffstats
path: root/iptables/xshared.c
diff options
context:
space:
mode:
Diffstat (limited to 'iptables/xshared.c')
-rw-r--r--iptables/xshared.c56
1 files changed, 48 insertions, 8 deletions
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 81c2581f..cccb8aec 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -9,12 +9,15 @@
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <xtables.h>
+#include <math.h>
#include "xshared.h"
#define XT_LOCK_NAME "/run/xtables.lock"
+#define BASE_MICROSECONDS 100000
/*
* Print out any special helps. A user might like to be able to add a --help
@@ -244,9 +247,15 @@ void xs_init_match(struct xtables_match *match)
match->init(match->m);
}
-bool xtables_lock(int wait)
+bool xtables_lock(int wait, struct timeval *wait_interval)
{
- int fd, waited = 0, i = 0;
+ struct timeval time_left, wait_time, waited_time;
+ int fd, i = 0;
+
+ time_left.tv_sec = wait;
+ time_left.tv_usec = 0;
+ waited_time.tv_sec = 0;
+ waited_time.tv_usec = 0;
fd = open(XT_LOCK_NAME, O_CREAT, 0600);
if (fd < 0)
@@ -255,12 +264,43 @@ bool xtables_lock(int wait)
while (1) {
if (flock(fd, LOCK_EX | LOCK_NB) == 0)
return true;
- else if (wait >= 0 && waited >= wait)
+ if (++i % 10 == 0) {
+ if (wait != -1)
+ fprintf(stderr, "Another app is currently holding the xtables lock; "
+ "still %lds %ldus time ahead to have a chance to grab the lock...\n",
+ time_left.tv_sec, time_left.tv_usec);
+ else
+ fprintf(stderr, "Another app is currently holding the xtables lock; "
+ "waiting for it to exit...\n");
+ }
+
+ wait_time = *wait_interval;
+ select(0, NULL, NULL, NULL, &wait_time);
+ if (wait == -1)
+ continue;
+
+ timeradd(&waited_time, wait_interval, &waited_time);
+ timersub(&time_left, wait_interval, &time_left);
+ if (!timerisset(&time_left))
return false;
- if (++i % 2 == 0)
- fprintf(stderr, "Another app is currently holding the xtables lock; "
- "waiting (%ds) for it to exit...\n", waited);
- waited++;
- sleep(1);
}
}
+
+void parse_wait_interval(const char *str, struct timeval *wait_interval)
+{
+ unsigned int usec;
+ int ret;
+
+ ret = sscanf(str, "%u", &usec);
+ if (ret == 1) {
+ if (usec > 999999)
+ xtables_error(PARAMETER_PROBLEM,
+ "too long usec wait %u > 999999 usec",
+ usec);
+
+ wait_interval->tv_sec = 0;
+ wait_interval->tv_usec = usec;
+ return;
+ }
+ xtables_error(PARAMETER_PROBLEM, "wait interval not numeric");
+}