diff options
Diffstat (limited to 'iptables/xshared.c')
-rw-r--r-- | iptables/xshared.c | 56 |
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"); +} |