]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-program-client: Disconnect asynchronously
authorAki Tuomi <aki.tuomi@dovecot.fi>
Mon, 17 Oct 2016 06:11:38 +0000 (09:11 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 19 Oct 2016 13:43:30 +0000 (16:43 +0300)
src/lib-program-client/program-client-private.h
src/lib-program-client/program-client-remote.c
src/lib-program-client/program-client.c

index fcf3a941b0e8dc01e75f8ca9e415ba3a2fe9c236..b18647c98195050f69c2b5e10ea71256dac10318 100644 (file)
@@ -47,12 +47,14 @@ struct program_client {
        program_client_callback_t *callback;
        void *context;
 
+       bool other_error;
        enum program_client_error error;
        int exit_code;
 
        int (*connect) (struct program_client * pclient);
        int (*close_output) (struct program_client * pclient);
-       int (*disconnect) (struct program_client * pclient, bool force);
+       void (*disconnect) (struct program_client * pclient, bool force);
+       void (*destroy) (struct program_client * pclient);
 
        bool debug:1;
        bool disconnected:1;
@@ -68,4 +70,8 @@ int program_client_connected(struct program_client *pclient);
 
 void program_client_fail(struct program_client *pclient, enum program_client_error error);
 
+void program_client_program_input(struct program_client *pclient);
+
+void program_client_disconnected(struct program_client *pclient);
+
 #endif
index a64f36f6b62812f59fa88b0ab858a6503fe00c91..f02f379b20a6a381f165ab6755a471dd268c0b77 100644 (file)
@@ -287,11 +287,11 @@ int program_client_remote_close_output(struct program_client *pclient)
 }
 
 static
-int program_client_remote_disconnect(struct program_client *pclient, bool force)
+void program_client_remote_disconnect(struct program_client *pclient, bool force)
 {
        struct program_client_remote *slclient =
                (struct program_client_remote *)pclient;
-       int ret = 0;
+       int ret;
 
        if (pclient->error == PROGRAM_CLIENT_ERROR_NONE && !slclient->noreply &&
            pclient->program_input != NULL && !force) {
@@ -306,14 +306,14 @@ int program_client_remote_disconnect(struct program_client *pclient, bool force)
 
                /* Get exit code */
                if (!pclient->program_input->eof)
-                       ret = -1;
+                       pclient->exit_code = -1;
                else
                        ret = pclient->exit_code;
        } else {
-               ret = 1;
+               pclient->exit_code = 1;
        }
 
-       return ret;
+       program_client_disconnected(pclient);
 }
 
 struct program_client *
index fb5df8e09bb52e80d03fd408967bfd51c93b1c78..750d9e537f02fdabb53dc7d1317bdb5ac657bffa 100644 (file)
@@ -119,21 +119,8 @@ void program_client_disconnect_extra_fds(struct program_client *pclient)
        }
 }
 
-static
-void program_client_disconnect(struct program_client *pclient, bool force)
+void program_client_disconnected(struct program_client *pclient)
 {
-       int ret, error = FALSE;
-
-       if (pclient->disconnected)
-               return;
-
-       if ((ret = program_client_close_output(pclient)) < 0)
-               error = TRUE;
-
-       program_client_disconnect_extra_fds(pclient);
-       if ((ret = pclient->disconnect(pclient, force)) < 0)
-               error = TRUE;
-
        if (pclient->program_input != NULL) {
                if (pclient->output_seekable)
                        i_stream_unref(&pclient->program_input);
@@ -143,8 +130,6 @@ void program_client_disconnect(struct program_client *pclient, bool force)
        if (pclient->program_output != NULL)
                o_stream_destroy(&pclient->program_output);
 
-       if (pclient->to != NULL)
-               timeout_remove(&pclient->to);
        if (pclient->io != NULL)
                io_remove(&pclient->io);
 
@@ -156,7 +141,8 @@ void program_client_disconnect(struct program_client *pclient, bool force)
        pclient->fd_in = pclient->fd_out = -1;
 
        pclient->disconnected = TRUE;
-       if (error && pclient->error == PROGRAM_CLIENT_ERROR_NONE) {
+
+       if (pclient->other_error && pclient->error == PROGRAM_CLIENT_ERROR_NONE) {
                pclient->error = PROGRAM_CLIENT_ERROR_OTHER;
        }
 
@@ -167,6 +153,28 @@ void program_client_disconnect(struct program_client *pclient, bool force)
                pclient->context);
 }
 
+static
+void program_client_disconnect(struct program_client *pclient, bool force)
+{
+       int ret;
+
+       if (pclient->disconnected)
+               return;
+       pclient->disconnected = TRUE;
+
+       if (pclient->to != NULL)
+               timeout_remove(&pclient->to);
+       if (pclient->io != NULL)
+               io_remove(&pclient->io);
+
+       if ((ret = program_client_close_output(pclient)) < 0)
+               pclient->other_error = TRUE;
+
+       program_client_disconnect_extra_fds(pclient);
+
+       pclient->disconnect(pclient, force);
+}
+
 void program_client_fail(struct program_client *pclient, enum program_client_error error)
 {
        if (pclient->error != PROGRAM_CLIENT_ERROR_NONE)
@@ -218,6 +226,7 @@ int program_client_program_output(struct program_client *pclient)
                                o_stream_get_error(output));
                        program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
                }
+
                return ret;
        }
 
@@ -278,7 +287,6 @@ int program_client_program_output(struct program_client *pclient)
        return 1;
 }
 
-static
 void program_client_program_input(struct program_client *pclient)
 {
        struct istream *input = pclient->program_input;
@@ -331,8 +339,15 @@ void program_client_program_input(struct program_client *pclient)
                                        program_client_disconnect(pclient, FALSE);
                        }
                }
-       } else
-               program_client_disconnect(pclient, FALSE);
+               if (program_client_input_pending(pclient))
+                       return;
+               if (!input->eof) {
+                       program_client_fail(pclient,
+                                           PROGRAM_CLIENT_ERROR_IO);
+                       return;
+               }
+       }
+       program_client_disconnect(pclient, FALSE);
 }
 
 static
@@ -512,6 +527,8 @@ void program_client_destroy(struct program_client **_pclient)
 
        program_client_disconnect(pclient, TRUE);
 
+       i_assert(pclient->callback == NULL);
+
        if (pclient->input != NULL)
                i_stream_unref(&pclient->input);
        if (pclient->program_input != NULL)
@@ -522,9 +539,14 @@ void program_client_destroy(struct program_client **_pclient)
                o_stream_unref(&pclient->output);
        if (pclient->seekable_output != NULL)
                i_stream_unref(&pclient->seekable_output);
+
        if (pclient->io != NULL)
                io_remove(&pclient->io);
        i_free(pclient->temp_prefix);
+
+       if (pclient->destroy != NULL)
+               pclient->destroy(pclient);
+
        pool_unref(&pclient->pool);
        *_pclient = NULL;
 }
@@ -608,7 +630,5 @@ void program_client_run_async(struct program_client *pclient, program_client_cal
                        program_client_callback(pclient, ret, context);
                        return;
                }
-       } else {
-               program_client_callback(pclient, ret, context);
        }
 }