]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master: ipc-client: Support aborting commands
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 5 Jul 2018 11:42:30 +0000 (14:42 +0300)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 13 Nov 2018 11:09:56 +0000 (13:09 +0200)
src/lib-master/ipc-client.c
src/lib-master/ipc-client.h

index 28d7217cafed4e98be3ef8b3af4c781fed8eebf4..93a2351dc34ca1ef1a94cc7ff8b130f8bbe3c4ab 100644 (file)
@@ -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);
+       }
 }
index e5c546dec63737ea3bc495cb9666f90fe655a21e..99bce160274750074c36ae55804f13637496b821 100644 (file)
@@ -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