This is an automated email from Gerrit. "Antonio Borneo <borneo.anto...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6841
-- gerrit commit f19b1dfc890423a64f8195381f8ee9e4be70dd28 Author: Antonio Borneo <borneo.anto...@gmail.com> Date: Thu Feb 3 18:24:20 2022 +0100 keep-alive: manage deadline per connection A GDB connection that is exchanging several messages will not need any keep-alive and calls kept_alive() to delay next keep-alive. If another GDB connection is present and is idle, it would need a keep-alive, but the keep-alive will not arrive due to the other connection calling kept_alive(). When two or more GDB connections are present, we cannot use a single deadline 'last_time' for all the connections. Use a per-connection 'last_time'. Let kept_alive() to update only the connection 'last_time'. When server doesn't need to send keep-alive, update 'last_time' as if the keep-alive was done. Implement a method to retrieve the oldest 'last_time' to compute the next keep-alive event. Change-Id: I3bb5aebe929273569e6f1d2613d6385b84a4e2ed Signed-off-by: Antonio Borneo <borneo.anto...@gmail.com> diff --git a/src/helper/log.c b/src/helper/log.c index 106d22867..6eee3d5b7 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -438,36 +438,50 @@ void keep_alive(void) int64_t current_time = timeval_ms(); int64_t delta_time = current_time - last_time; - if (delta_time > KEEP_ALIVE_TIMEOUT_MS) { - last_time = current_time; + if (delta_time <= KEEP_ALIVE_KICK_TIME_MS) + return; + if (delta_time > KEEP_ALIVE_TIMEOUT_MS) gdb_timeout_warning(delta_time); - } - if (delta_time > KEEP_ALIVE_KICK_TIME_MS) { + /* some server could have been self-kept-alive */ + last_time = server_older_kept_alive_time(); + if (last_time > current_time) { + /* INT64_MAX: no connection requires keep-alive, retry later */ last_time = current_time; + return; + } + delta_time = current_time - last_time; + if (delta_time <= KEEP_ALIVE_KICK_TIME_MS) + return; - /* this will keep the GDB connection alive */ - server_keep_clients_alive(); + /* this will keep the GDB connection alive */ + server_keep_clients_alive(); - /* DANGER!!!! do not add code to invoke e.g. target event processing, - * jim timer processing, etc. it can cause infinite recursion + - * jim event callbacks need to happen at a well defined time, - * not anywhere keep_alive() is invoked. - * - * These functions should be invoked at a well defined spot in server.c - */ - } + /* some connection could have failed keep-alive, get status */ + last_time = server_older_kept_alive_time(); + if (last_time > current_time) + last_time = current_time; + + /* DANGER!!!! do not add code to invoke e.g. target event processing, + * jim timer processing, etc. it can cause infinite recursion + + * jim event callbacks need to happen at a well defined time, + * not anywhere keep_alive() is invoked. + * + * These functions should be invoked at a well defined spot in server.c + */ } -/* reset keep alive timer without sending message */ -void kept_alive(void) +/* reset connection's keep alive timer without sending message + * argument's value can be INT64_MAX + */ +void kept_alive(int64_t *last_kept_alive_time) { int64_t current_time = timeval_ms(); - int64_t delta_time = current_time - last_time; + int64_t delta_time = current_time - *last_kept_alive_time; - last_time = current_time; + *last_kept_alive_time = current_time; if (delta_time > KEEP_ALIVE_TIMEOUT_MS) gdb_timeout_warning(delta_time); diff --git a/src/helper/log.h b/src/helper/log.h index f0378ae79..5c4d1f7e0 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -78,7 +78,7 @@ int set_log_output(struct command_context *cmd_ctx, FILE *output); int log_register_commands(struct command_context *cmd_ctx); void keep_alive(void); -void kept_alive(void); +void kept_alive(int64_t *last_kept_alive_time); void alive_sleep(uint64_t ms); void busy_sleep(uint64_t ms); diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 0944db4d3..0751cbab9 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -534,7 +534,7 @@ int gdb_put_packet(struct connection *connection, char *buffer, int len) gdb_con->busy = false; /* we sent some data, reset timer for keep alive messages */ - kept_alive(); + kept_alive(&connection->last_kept_alive_time); return retval; } @@ -3665,6 +3665,7 @@ static void gdb_keep_client_alive(struct connection *connection) switch (gdb_con->output_flag) { case GDB_OUTPUT_NO: /* no need for keep-alive */ + kept_alive(&connection->last_kept_alive_time); break; case GDB_OUTPUT_ALL: /* send an empty O packet */ diff --git a/src/server/server.c b/src/server/server.c index 1bd84e47e..542662f83 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -78,6 +78,7 @@ static int add_connection(struct service *service, struct command_context *cmd_c c->cmd_ctx = copy_command_context(cmd_ctx); c->service = service; c->input_pending = false; + c->last_kept_alive_time = INT64_MAX; c->priv = NULL; c->next = NULL; @@ -429,6 +430,19 @@ void server_keep_clients_alive(void) s->keep_client_alive(c); } +int64_t server_older_kept_alive_time(void) +{ + int64_t older = INT64_MAX; + + for (struct service *s = services; s; s = s->next) + if (s->keep_client_alive) + for (struct connection *c = s->connections; c; c = c->next) + if (c->last_kept_alive_time && older > c->last_kept_alive_time) + older = c->last_kept_alive_time; + + return older; +} + int server_loop(struct command_context *command_context) { struct service *service; diff --git a/src/server/server.h b/src/server/server.h index e8b5e5ac0..d8cf01e8f 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -52,6 +52,7 @@ struct connection { struct service *service; bool input_pending; void *priv; + int64_t last_kept_alive_time; struct connection *next; }; @@ -107,6 +108,7 @@ void server_free(void); void exit_on_signal(int sig); void server_keep_clients_alive(void); +int64_t server_older_kept_alive_time(void); int server_loop(struct command_context *command_context); --