From 07e2107ef0cbc1b81864c3c0f0ef297a9dfff44d Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Mon, 14 Feb 2022 10:35:56 +0100 Subject: xshared: Implement xtables lock timeout using signals Previously, if a lock timeout is specified using `-wN `, flock() is called using LOCK_NB in a loop with a sleep. This results in two issues. The first issue is that the process may wait longer than necessary when the lock becomes available. For this the `-W` option was added, but this requires fine-tuning. The second issue is that if lock contention is high, invocations using `-w` (without a timeout) will always win lock acquisition from invocations that use `-w N`. This is because invocations using `-w` are actively waiting on the lock whereas those using `-w N` only check from time to time whether the lock is free, which will never be the case. This patch removes the sleep loop and deprecates the `-W` option (making it non-functional). Instead, flock() is always called in a blocking fashion, but the alarm() function is used with a non-SA_RESTART signal handler to cancel the system call. Signed-off-by: Jethro Beekman Signed-off-by: Florian Westphal --- iptables/iptables-restore.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'iptables/iptables-restore.c') diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index 3c0a2389..1917fb23 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -22,10 +22,6 @@ static int counters, verbose, noflush, wait; -static struct timeval wait_interval = { - .tv_sec = 1, -}; - /* Keeping track of external matches and targets. */ static const struct option options[] = { {.name = "counters", .has_arg = 0, .val = 'c'}, @@ -51,7 +47,6 @@ static void print_usage(const char *name, const char *version) " [ --help ]\n" " [ --noflush ]\n" " [ --wait=\n" - " [ --wait-interval=\n" " [ --table= ]\n" " [ --modprobe= ]\n", name); } @@ -101,6 +96,7 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb, FILE *in; int in_table = 0, testing = 0; const char *tablename = NULL; + bool wait_interval_set = false; line = 0; lock = XT_LOCK_NOT_ACQUIRED; @@ -135,7 +131,8 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb, wait = parse_wait_time(argc, argv); break; case 'W': - parse_wait_interval(argc, argv, &wait_interval); + parse_wait_interval(argc, argv); + wait_interval_set = true; break; case 'M': xtables_modprobe_program = optarg; @@ -165,7 +162,7 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb, } else in = stdin; - if (!wait_interval.tv_sec && !wait) { + if (wait_interval_set && !wait) { fprintf(stderr, "Option --wait-interval requires option --wait\n"); exit(1); } @@ -203,7 +200,7 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb, in_table = 0; } else if ((buffer[0] == '*') && (!in_table)) { /* Acquire a lock before we create a new table handle */ - lock = xtables_lock_or_exit(wait, &wait_interval); + lock = xtables_lock_or_exit(wait); /* New table */ char *table; -- cgit v1.2.3