From: Stephan Bosch Date: Sun, 25 Feb 2018 10:43:04 +0000 (+0100) Subject: lib-program-client: Initialize dot streams right after the connection is established. X-Git-Tag: 2.3.9~2087 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6acc2464b039fea6a2528b493beff60869a0b761;p=thirdparty%2Fdovecot%2Fcore.git lib-program-client: Initialize dot streams right after the connection is established. This avoids creating the dot streams in the input/output handlers, which makes the code cleaner and easier to port to using iostream-pump. --- diff --git a/src/lib-program-client/program-client-private.h b/src/lib-program-client/program-client-private.h index cf4f4d14c9..7abad7ed4b 100644 --- a/src/lib-program-client/program-client-private.h +++ b/src/lib-program-client/program-client-private.h @@ -41,8 +41,8 @@ struct program_client { struct timeout *to; struct timeval start_time; - struct istream *input, *program_input, *dot_input; - struct ostream *output, *program_output, *dot_output; + struct istream *input, *program_input, *raw_program_input; + struct ostream *output, *program_output, *raw_program_output; ARRAY(struct program_client_extra_fd) extra_fds; @@ -62,8 +62,6 @@ struct program_client { bool debug:1; bool disconnected:1; bool output_seekable:1; - bool input_dot_created:1; - bool output_dot_created:1; bool destroying:1; }; diff --git a/src/lib-program-client/program-client-remote.c b/src/lib-program-client/program-client-remote.c index 63bf8616e1..e0dd99e43b 100644 --- a/src/lib-program-client/program-client-remote.c +++ b/src/lib-program-client/program-client-remote.c @@ -234,10 +234,9 @@ program_client_remote_connected(struct program_client_remote *prclient) program_client_init_streams(pclient); if (!prclient->noreply) { - struct istream *is = pclient->program_input; - pclient->program_input = - program_client_istream_create(pclient, - pclient->program_input); + struct istream *is = pclient->raw_program_input; + pclient->raw_program_input = + program_client_istream_create(pclient, is); i_stream_unref(&is); } @@ -263,11 +262,11 @@ program_client_remote_connected(struct program_client_remote *prclient) } str_append_c(str, '\n'); - if (o_stream_send(pclient->program_output, + if (o_stream_send(pclient->raw_program_output, str_data(str), str_len(str)) < 0) { i_error("write(%s) failed: %s", - o_stream_get_name(pclient->program_output), - o_stream_get_error(pclient->program_output)); + o_stream_get_name(pclient->raw_program_output), + o_stream_get_error(pclient->raw_program_output)); program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return; } @@ -554,7 +553,7 @@ program_client_remote_disconnect(struct program_client *pclient, bool force) timeout_remove(&prclient->to_retry); - if (pclient->program_input == NULL) { + if (pclient->raw_program_input == NULL) { /* nothing */ } else if (pclient->error == PROGRAM_CLIENT_ERROR_NONE && !prclient->noreply && !force) { @@ -563,15 +562,15 @@ program_client_remote_disconnect(struct program_client *pclient, bool force) /* Skip any remaining program output and parse the exit code */ while (i_stream_read_more - (pclient->program_input, &data, &size) > 0) { - i_stream_skip(pclient->program_input, size); + (pclient->raw_program_input, &data, &size) > 0) { + i_stream_skip(pclient->raw_program_input, size); } /* Check for error and EOF. Since we're disconnected, always mark an internal error when not all input is read. This is generally unlikely to occur. */ - if (pclient->program_input->stream_errno != 0 || - i_stream_have_bytes_left(pclient->program_input)) { + if (pclient->raw_program_input->stream_errno != 0 || + i_stream_have_bytes_left(pclient->raw_program_input)) { pclient->exit_code = PROGRAM_CLIENT_EXIT_INTERNAL_FAILURE; } diff --git a/src/lib-program-client/program-client.c b/src/lib-program-client/program-client.c index c29473f4e8..06acec091a 100644 --- a/src/lib-program-client/program-client.c +++ b/src/lib-program-client/program-client.c @@ -92,13 +92,10 @@ program_client_disconnect_extra_fds(struct program_client *pclient) void program_client_disconnected(struct program_client *pclient) { - if (pclient->program_input != NULL) { - if (pclient->set.use_dotstream) - i_stream_unref(&pclient->program_input); - else - i_stream_destroy(&pclient->program_input); - } + i_stream_destroy(&pclient->program_input); o_stream_destroy(&pclient->program_output); + i_stream_destroy(&pclient->raw_program_input); + o_stream_destroy(&pclient->raw_program_output); io_remove(&pclient->io); @@ -198,16 +195,6 @@ program_client_program_output(struct program_client *pclient) return ret; } - /* initialize dot stream if required */ - if (!pclient->output_dot_created && - pclient->set.use_dotstream && - output != NULL) { - pclient->dot_output = o_stream_create_dot(output, FALSE); - pclient->output_dot_created = TRUE; - } - if (pclient->dot_output != NULL) - output = pclient->dot_output; - if (input != NULL && output != NULL) { /* transfer provided input stream to output towards program */ res = o_stream_send_istream(output, input); @@ -247,7 +234,8 @@ program_client_program_output(struct program_client *pclient) } if (ret == 0) return 0; - o_stream_unref(&pclient->dot_output); + o_stream_unref(&pclient->program_output); + o_stream_unref(&pclient->raw_program_output); } if (input == NULL) { @@ -274,22 +262,19 @@ void program_client_program_input(struct program_client *pclient) int ret = 0; if (input != NULL) { - /* initialize dot stream if required */ - if (!pclient->input_dot_created && - pclient->set.use_dotstream) { - pclient->dot_input = i_stream_create_dot(input, FALSE); - pclient->input_dot_created = TRUE; - } - if (pclient->dot_input != NULL) - input = pclient->dot_input; - /* transfer input from program to provided output stream */ if (output != NULL) { res = o_stream_send_istream(output, input); switch (res) { case OSTREAM_SEND_ISTREAM_RESULT_FINISHED: - i_stream_unref(&pclient->dot_input); - input = pclient->program_input; + /* return to raw program input */ + if (pclient->program_input == + pclient->raw_program_input) + break; + i_stream_unref(&pclient->program_input); + input = pclient->program_input = + pclient->raw_program_input; + i_stream_ref(pclient->program_input); break; case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT: case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: @@ -311,7 +296,7 @@ void program_client_program_input(struct program_client *pclient) } } - /* read (the remainder of) the outer stream */ + /* read (the remainder of) the raw program input */ while ((ret=i_stream_read_more(input, &data, &size)) > 0) i_stream_skip(input, size); if (ret == 0) @@ -368,6 +353,29 @@ int program_client_connected(struct program_client *pclient) { int ret = 1; + /* finish creating program input */ + if (pclient->raw_program_input != NULL) { + struct istream *input = pclient->raw_program_input; + + /* initialize dot input stream if required */ + if (pclient->set.use_dotstream) + input = i_stream_create_dot(input, FALSE); + else + i_stream_ref(input); + pclient->program_input = input; + } + /* finish creating program output */ + if (pclient->raw_program_output != NULL) { + struct ostream *output = pclient->raw_program_output; + + /* initialize dot output stream if required */ + if (pclient->set.use_dotstream) + output = o_stream_create_dot(output, FALSE); + else + o_stream_ref(output); + pclient->program_output = output; + } + pclient->start_time = ioloop_timeval; timeout_remove(&pclient->to); if (pclient->set.input_idle_timeout_msecs != 0) { @@ -486,18 +494,22 @@ void program_client_init_streams(struct program_client *pclient) { /* Create streams for normal program I/O */ if (pclient->fd_out >= 0) { - pclient->program_output = - o_stream_create_fd(pclient->fd_out, - MAX_OUTPUT_BUFFER_SIZE); - o_stream_set_name(pclient->program_output, "program stdin"); - o_stream_set_no_error_handling(pclient->program_output, TRUE); + struct ostream *program_output; + + program_output = o_stream_create_fd(pclient->fd_out, + MAX_OUTPUT_BUFFER_SIZE); + o_stream_set_name(program_output, "program stdin"); + o_stream_set_no_error_handling(program_output, TRUE); + pclient->raw_program_output = program_output; } if (pclient->fd_in >= 0) { - pclient->program_input = - i_stream_create_fd(pclient->fd_in, (size_t)-1); - i_stream_set_name(pclient->program_input, "program stdout"); + struct istream *program_input; + + program_input = i_stream_create_fd(pclient->fd_in, (size_t)-1); + i_stream_set_name(program_input, "program stdout"); pclient->io = io_add(pclient->fd_in, IO_READ, program_client_program_input, pclient); + pclient->raw_program_input = program_input; } /* Create streams for additional output through side-channel fds */ @@ -534,10 +546,12 @@ void program_client_destroy(struct program_client **_pclient) i_assert(pclient->callback == NULL); i_stream_unref(&pclient->input); - i_stream_unref(&pclient->dot_input); + o_stream_unref(&pclient->output); + i_stream_unref(&pclient->program_input); o_stream_unref(&pclient->program_output); - o_stream_unref(&pclient->output); + i_stream_unref(&pclient->raw_program_input); + o_stream_unref(&pclient->raw_program_output); io_remove(&pclient->io);