From: Aki Tuomi Date: Mon, 17 Oct 2016 06:11:38 +0000 (+0300) Subject: lib-program-client: Disconnect asynchronously X-Git-Tag: 2.2.26~101 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=658ef8bb6209db4f8c9824d1f99731210b8450c1;p=thirdparty%2Fdovecot%2Fcore.git lib-program-client: Disconnect asynchronously --- diff --git a/src/lib-program-client/program-client-private.h b/src/lib-program-client/program-client-private.h index fcf3a941b0..b18647c981 100644 --- a/src/lib-program-client/program-client-private.h +++ b/src/lib-program-client/program-client-private.h @@ -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 diff --git a/src/lib-program-client/program-client-remote.c b/src/lib-program-client/program-client-remote.c index a64f36f6b6..f02f379b20 100644 --- a/src/lib-program-client/program-client-remote.c +++ b/src/lib-program-client/program-client-remote.c @@ -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 * diff --git a/src/lib-program-client/program-client.c b/src/lib-program-client/program-client.c index fb5df8e09b..750d9e537f 100644 --- a/src/lib-program-client/program-client.c +++ b/src/lib-program-client/program-client.c @@ -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); } }