diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-07-26 03:46:39 +0200 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2014-07-26 03:47:03 +0200 |
commit | c430d3278b91369204c83cd135673a5d5cded699 (patch) | |
tree | 269d91f785c2c1e3ff5ed28db4bd5002203c6850 | |
parent | e46cbd2f89f0be8e4a2423c065cf6b2e6ebcfea3 (diff) |
proto-shell: fix setup/renew race condition
If a renew event arrives before the setup event has been processed, the
renew event needs to be deferred, otherwise interfaces can get stuck
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-rw-r--r-- | proto-shell.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/proto-shell.c b/proto-shell.c index d85a8d7..5f2224b 100644 --- a/proto-shell.c +++ b/proto-shell.c @@ -71,6 +71,7 @@ struct proto_shell_state { enum proto_shell_sm sm; bool proto_task_killed; + bool renew_pending; int last_error; @@ -162,11 +163,18 @@ proto_shell_handler(struct interface_proto_state *proto, } else if (cmd == PROTO_CMD_RENEW) { if (!(handler->proto.flags & PROTO_FLAG_RENEW_AVAILABLE)) return 0; + + if (state->script_task.uloop.pending) { + state->renew_pending = true; + return 0; + } + action = "renew"; } else { if (state->sm == S_TEARDOWN) return 0; + state->renew_pending = false; if (state->script_task.uloop.pending) { if (state->sm != S_SETUP_ABORT) { uloop_timeout_set(&state->teardown_timeout, 1000); @@ -256,6 +264,9 @@ proto_shell_task_finish(struct proto_shell_state *state, if (task == &state->proto_task) proto_shell_handler(&state->proto, PROTO_CMD_TEARDOWN, false); + if (task == &state->script_task && state->renew_pending) + proto_shell_handler(&state->proto, PROTO_CMD_RENEW, + false); break; case S_SETUP_ABORT: |