From: Timo Sirainen Date: Thu, 5 Jul 2018 11:42:30 +0000 (+0300) Subject: lib-master: ipc-client: Support aborting commands X-Git-Tag: 2.2.36.1~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=30b2cff61a4cd6a9c53b57dde62c295f7ec5b9a3;p=thirdparty%2Fdovecot%2Fcore.git lib-master: ipc-client: Support aborting commands --- diff --git a/src/lib-master/ipc-client.c b/src/lib-master/ipc-client.c index 09d8b51bba..62d698919a 100644 --- a/src/lib-master/ipc-client.c +++ b/src/lib-master/ipc-client.c @@ -29,6 +29,7 @@ struct ipc_client { struct istream *input; struct ostream *output; struct ipc_client_cmd *cmds_head, *cmds_tail; + unsigned int aborted_cmds_count; }; static void ipc_client_disconnect(struct ipc_client *client); @@ -39,7 +40,10 @@ static void ipc_client_input_line(struct ipc_client *client, const char *line) enum ipc_client_cmd_state state; bool disconnect = FALSE; - if (cmd == NULL) { + if (client->aborted_cmds_count > 0) { + /* the command was already aborted */ + cmd = NULL; + } else if (cmd == NULL) { i_error("IPC proxy sent unexpected input: %s", line); return; } @@ -62,10 +66,17 @@ static void ipc_client_input_line(struct ipc_client *client, const char *line) break; } - if (state != IPC_CLIENT_CMD_STATE_REPLY) - DLLIST2_REMOVE(&client->cmds_head, &client->cmds_tail, cmd); - cmd->callback(state, line, cmd->context); - i_free(cmd); + if (state != IPC_CLIENT_CMD_STATE_REPLY) { + if (cmd != NULL) + DLLIST2_REMOVE(&client->cmds_head, + &client->cmds_tail, cmd); + else + client->aborted_cmds_count--; + } + if (cmd != NULL) { + cmd->callback(state, line, cmd->context); + i_free(cmd); + } if (disconnect) ipc_client_disconnect(client); } @@ -159,8 +170,9 @@ static void ipc_client_cmd_connect_failed(struct ipc_client *client) timeout_remove(&client->to_failed); } -void ipc_client_cmd(struct ipc_client *client, const char *cmd, - ipc_client_callback_t *callback, void *context) +struct ipc_client_cmd * +ipc_client_cmd(struct ipc_client *client, const char *cmd, + ipc_client_callback_t *callback, void *context) { struct ipc_client_cmd *ipc_cmd; struct const_iovec iov[2]; @@ -185,4 +197,24 @@ void ipc_client_cmd(struct ipc_client *client, const char *cmd, iov[1].iov_len = 1; o_stream_nsendv(client->output, iov, N_ELEMENTS(iov)); } + return ipc_cmd; +} + +void ipc_client_cmd_abort(struct ipc_client *client, + struct ipc_client_cmd **_cmd) +{ + struct ipc_client_cmd *cmd = *_cmd; + + *_cmd = NULL; + cmd->callback = NULL; + /* Free the command only if it's the oldest. Free also other such + commands in case they were aborted earlier. */ + while (client->cmds_head != NULL && + client->cmds_head->callback == NULL) { + struct ipc_client_cmd *head = client->cmds_head; + + client->aborted_cmds_count++; + DLLIST2_REMOVE(&client->cmds_head, &client->cmds_tail, head); + i_free(head); + } } diff --git a/src/lib-master/ipc-client.h b/src/lib-master/ipc-client.h index e5c546dec6..99bce16027 100644 --- a/src/lib-master/ipc-client.h +++ b/src/lib-master/ipc-client.h @@ -14,8 +14,11 @@ struct ipc_client * ipc_client_init(const char *ipc_socket_path); void ipc_client_deinit(struct ipc_client **client); -void ipc_client_cmd(struct ipc_client *client, const char *cmd, - ipc_client_callback_t *callback, void *context) +struct ipc_client_cmd * +ipc_client_cmd(struct ipc_client *client, const char *cmd, + ipc_client_callback_t *callback, void *context) ATTR_NULL(4); +void ipc_client_cmd_abort(struct ipc_client *client, + struct ipc_client_cmd **cmd); #endif