diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 57b71bcac4..489f49c743 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -86,7 +86,6 @@ VLOG_DEFINE_THIS_MODULE(main); -static unixctl_cb_func ovn_controller_exit; static unixctl_cb_func ct_zone_list; static unixctl_cb_func extend_table_list; static unixctl_cb_func inject_pkt; @@ -4482,11 +4481,6 @@ flow_output_lflow_output_handler(struct engine_node *node, return true; } -struct ovn_controller_exit_args { - bool *exiting; - bool *restart; -}; - /* Handles sbrec_chassis changes. * If a new chassis is added or removed return false, so that * flows are recomputed. For any updates, there is no need for @@ -4561,9 +4555,7 @@ int main(int argc, char *argv[]) { struct unixctl_server *unixctl; - bool exiting; - bool restart; - struct ovn_controller_exit_args exit_args = {&exiting, &restart}; + struct ovn_exit_args exit_args = {}; int retval; /* Read from system-id-override file once on startup. */ @@ -4583,7 +4575,7 @@ main(int argc, char *argv[]) if (retval) { exit(EXIT_FAILURE); } - unixctl_command_register("exit", "", 0, 1, ovn_controller_exit, + unixctl_command_register("exit", "", 0, 1, ovn_exit_command_callback, &exit_args); daemonize_complete(); @@ -5068,10 +5060,8 @@ main(int argc, char *argv[]) VLOG_INFO("OVN internal version is : [%s]", ovn_version); /* Main loop. */ - exiting = false; - restart = false; bool sb_monitor_all = false; - while (!exiting) { + while (!exit_args.exiting) { memory_run(); if (memory_should_report()) { struct simap usage = SIMAP_INITIALIZER(&usage); @@ -5492,7 +5482,7 @@ main(int argc, char *argv[]) unixctl_server_run(unixctl); unixctl_server_wait(unixctl); - if (exiting || pending_pkt.conn) { + if (exit_args.exiting || pending_pkt.conn) { poll_immediate_wake(); } @@ -5543,7 +5533,7 @@ main(int argc, char *argv[]) memory_wait(); poll_block(); if (should_service_stop()) { - exiting = true; + exit_args.exiting = true; } } @@ -5551,7 +5541,7 @@ main(int argc, char *argv[]) engine_cleanup(); /* It's time to exit. Clean up the databases if we are not restarting */ - if (!restart) { + if (!exit_args.restart) { bool done = !ovsdb_idl_has_ever_connected(ovnsb_idl_loop.idl); while (!done) { update_sb_db(ovs_idl_loop.idl, ovnsb_idl_loop.idl, @@ -5603,7 +5593,6 @@ main(int argc, char *argv[]) } free(ovn_version); - unixctl_server_destroy(unixctl); lflow_destroy(); ofctrl_destroy(); pinctrl_destroy(); @@ -5627,6 +5616,8 @@ main(int argc, char *argv[]) if (cli_system_id) { free(cli_system_id); } + ovn_exit_args_finish(&exit_args); + unixctl_server_destroy(unixctl); service_stop(); ovsrcu_exit(); @@ -5750,16 +5741,6 @@ usage(void) exit(EXIT_SUCCESS); } -static void -ovn_controller_exit(struct unixctl_conn *conn, int argc, - const char *argv[], void *exit_args_) -{ - struct ovn_controller_exit_args *exit_args = exit_args_; - *exit_args->exiting = true; - *exit_args->restart = argc == 2 && !strcmp(argv[1], "--restart"); - unixctl_command_reply(conn, NULL); -} - static void ct_zone_list(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, void *ct_zones_) diff --git a/lib/ovn-util.c b/lib/ovn-util.c index 561e82093a..bf15fef2b7 100644 --- a/lib/ovn-util.c +++ b/lib/ovn-util.c @@ -1092,3 +1092,34 @@ void flow_collector_ids_clear(struct flow_collector_ids *ids) flow_collector_ids_destroy(ids); flow_collector_ids_init(ids); } + +/* Call for the unixctl command that will store the connection and + * set the appropriate conditions. */ +void +ovn_exit_command_callback(struct unixctl_conn *conn, int argc, + const char *argv[], void *exit_args_) +{ + struct ovn_exit_args *exit_args = exit_args_; + + exit_args->n_conns++; + exit_args->conns = xrealloc(exit_args->conns, + exit_args->n_conns * sizeof *exit_args->conns); + + exit_args->exiting = true; + exit_args->conns[exit_args->n_conns - 1] = conn; + + if (!exit_args->restart) { + exit_args->restart = argc == 2 && !strcmp(argv[1], "--restart"); + } +} + +/* Reply to all waiting unixctl connections and free the connection array. + * This function should be called after the heaviest cleanup has finished. */ +void +ovn_exit_args_finish(struct ovn_exit_args *exit_args) +{ + for (size_t i = 0; i < exit_args->n_conns; i++) { + unixctl_command_reply(exit_args->conns[i], NULL); + } + free(exit_args->conns); +} diff --git a/lib/ovn-util.h b/lib/ovn-util.h index 7510fda4be..a0bceccc6d 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -398,4 +398,16 @@ bool flow_collector_ids_lookup(const struct flow_collector_ids *, uint32_t); void flow_collector_ids_destroy(struct flow_collector_ids *); void flow_collector_ids_clear(struct flow_collector_ids *); +/* Utilities around properly handling exit command. */ +struct ovn_exit_args { + struct unixctl_conn **conns; + size_t n_conns; + bool exiting; + bool restart; +}; + +void ovn_exit_command_callback(struct unixctl_conn *conn, int argc, + const char *argv[], void *exit_args_); +void ovn_exit_args_finish(struct ovn_exit_args *exit_args); + #endif /* OVN_UTIL_H */ diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 234b7e9147..a551d88cde 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -47,7 +47,6 @@ VLOG_DEFINE_THIS_MODULE(ovn_northd); -static unixctl_cb_func ovn_northd_exit; static unixctl_cb_func ovn_northd_pause; static unixctl_cb_func ovn_northd_resume; static unixctl_cb_func ovn_northd_is_paused; @@ -765,7 +764,7 @@ main(int argc, char *argv[]) int res = EXIT_SUCCESS; struct unixctl_server *unixctl; int retval; - bool exiting; + struct ovn_exit_args exit_args = {}; int n_threads = 1; struct northd_state state = { .had_lock = false, @@ -787,7 +786,8 @@ main(int argc, char *argv[]) if (retval) { exit(EXIT_FAILURE); } - unixctl_command_register("exit", "", 0, 0, ovn_northd_exit, &exiting); + unixctl_command_register("exit", "", 0, 0, ovn_exit_command_callback, + &exit_args); unixctl_command_register("pause", "", 0, 0, ovn_northd_pause, &state); unixctl_command_register("resume", "", 0, 0, ovn_northd_resume, &state); unixctl_command_register("is-paused", "", 0, 0, ovn_northd_is_paused, @@ -872,10 +872,9 @@ main(int argc, char *argv[]) run_update_worker_pool(n_threads); /* Main loop. */ - exiting = false; bool recompute = false; - while (!exiting) { + while (!exit_args.exiting) { update_ssl_config(); memory_run(); if (memory_should_report()) { @@ -1010,7 +1009,7 @@ main(int argc, char *argv[]) unixctl_server_run(unixctl); unixctl_server_wait(unixctl); memory_wait(); - if (exiting) { + if (exit_args.exiting) { poll_immediate_wake(); } @@ -1041,15 +1040,16 @@ main(int argc, char *argv[]) stopwatch_stop(NORTHD_LOOP_STOPWATCH_NAME, time_msec()); poll_block(); if (should_service_stop()) { - exiting = true; + exit_args.exiting = true; } stopwatch_start(NORTHD_LOOP_STOPWATCH_NAME, time_msec()); } inc_proc_northd_cleanup(); - unixctl_server_destroy(unixctl); ovsdb_idl_loop_destroy(&ovnnb_idl_loop); ovsdb_idl_loop_destroy(&ovnsb_idl_loop); + ovn_exit_args_finish(&exit_args); + unixctl_server_destroy(unixctl); service_stop(); run_update_worker_pool(0); ovsrcu_exit(); @@ -1057,16 +1057,6 @@ main(int argc, char *argv[]) exit(res); } -static void -ovn_northd_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, - const char *argv[] OVS_UNUSED, void *exiting_) -{ - bool *exiting = exiting_; - *exiting = true; - - unixctl_command_reply(conn, NULL); -} - static void ovn_northd_pause(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, void *state_)