proto-shell: fix setup/renew race condition
authorFelix Fietkau <nbd@openwrt.org>
Sat, 26 Jul 2014 01:46:39 +0000 (03:46 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 26 Jul 2014 01:47:03 +0000 (03:47 +0200)
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>
proto-shell.c

index d85a8d7e022bd2808c88b5d6afa0a5fd4c3bdfef..5f2224b3d11309d283adabb60b6100ada588fa0c 100644 (file)
@@ -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: