summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorRuss Allbery <eagle@eyrie.org>2014-01-21 22:23:50 -0800
committerRuss Allbery <rra@stanford.edu>2014-01-22 12:25:05 -0800
commit074e56057b8da3f3783c81f47324f12581463d1d (patch)
tree5430deaba02cf0e2c55f5eb0ac933e78ed339365 /server
parent7d2f2dbe8b3ccd28bbae15553cce56334c53444d (diff)
Use an evbuffer to store input data for a process
Start isolating the process event loop from the rest of the code by not reusing the struct iovec representation of the input data. Instead, convert it to an evbuffer first. This does make another copy of the data. We will rethink this if it shows up as a performance issue. Change-Id: Ie37dea0e9b4a58fa4f481ed0a4fd5ba8bb7ebdab Reviewed-on: https://gerrit.stanford.edu/1389 Reviewed-by: Russ Allbery <rra@stanford.edu> Tested-by: Russ Allbery <rra@stanford.edu>
Diffstat (limited to 'server')
-rw-r--r--server/commands.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/server/commands.c b/server/commands.c
index 84348d2..0143b24 100644
--- a/server/commands.c
+++ b/server/commands.c
@@ -35,17 +35,23 @@
* themselves when needed.
*/
struct process {
- struct event_base *loop; /* Event base for the process event loop. */
- struct bufferevent *inout; /* Input and output from process. */
- struct bufferevent *err; /* Standard error from process. */
- struct event *sigchld; /* Handle the SIGCHLD signal for exit. */
- struct evbuffer *output; /* Buffer of output from process. */
struct client *client; /* Pointer to corresponding remctl client. */
+
+ /* Process data. */
socket_type stdinout_fd; /* File descriptor for input and output. */
socket_type stderr_fd; /* File descriptor for standard error. */
- struct iovec *input; /* Data to pass on standard input. */
pid_t pid; /* Process ID of child. */
int status; /* Exit status. */
+
+ /* Event loop. */
+ struct event_base *loop; /* Event base for the process event loop. */
+ struct bufferevent *inout; /* Input and output from process. */
+ struct bufferevent *err; /* Standard error from process. */
+ struct event *sigchld; /* Handle the SIGCHLD signal for exit. */
+ struct evbuffer *input; /* Buffer of input to process. */
+ struct evbuffer *output; /* Buffer of output from process. */
+
+ /* State flags. */
bool reaped; /* Whether we've reaped the process. */
bool saw_output; /* Whether we saw process output. */
};
@@ -235,8 +241,7 @@ server_process_output(struct client *client, struct process *process)
else {
writecb = handle_input_end;
bufferevent_enable(process->inout, EV_READ | EV_WRITE);
- if (bufferevent_write(process->inout, process->input->iov_base,
- process->input->iov_len) < 0)
+ if (bufferevent_write_buffer(process->inout, process->input) < 0)
sysdie("cannot queue input for process");
}
if (client->protocol == 1) {
@@ -692,14 +697,21 @@ create_argv_command(struct confline *cline, struct process *process,
else
stdin_arg = (size_t) cline->stdin_arg;
for (i = 1, j = 1; i < count; i++) {
+ const char *data = argv[i]->iov_base;
+ size_t length = argv[i]->iov_len;
+
if (i == stdin_arg) {
- process->input = argv[i];
+ process->input = evbuffer_new();
+ if (process->input == NULL)
+ die("internal error: cannot create input buffer");
+ if (evbuffer_add(process->input, data, length) < 0)
+ die("internal error: cannot add data to input buffer");
continue;
}
- if (argv[i]->iov_len == 0)
+ if (length == 0)
req_argv[j] = xstrdup("");
else
- req_argv[j] = xstrndup(argv[i]->iov_base, argv[i]->iov_len);
+ req_argv[j] = xstrndup(data, length);
j++;
}
req_argv[j] = NULL;