summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorRuss Allbery <eagle@eyrie.org>2018-04-22 17:36:14 -0700
committerRuss Allbery <eagle@eyrie.org>2018-04-22 17:36:14 -0700
commit1e7eb6b986cf73f5fb2ef3c46eff17c928ac6417 (patch)
treee8a1e1ef9cd9cca8d1275c82cd1689721117750c /server
parent5aeb80f6579fdb95e2cef764dad8f58b56d42c2b (diff)
Fix child output truncation on early stdin exit
Fix a bug where output could have been truncated for a command run by the server that was accepting an argument on standard input, if it exited before reading all of the input data. Incorrect server logic disabled reads from the child process on write failure, so could have missed the last buffer of output from the child. This was only seen under valgrind testing, not reported as a bug, so it's not clear how widespread of a problem this was.
Diffstat (limited to 'server')
-rw-r--r--server/process.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/server/process.c b/server/process.c
index 7037bc1..1f10aa6 100644
--- a/server/process.c
+++ b/server/process.c
@@ -6,9 +6,10 @@
* with the child process.
*
* Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2018 Russ Allbery <eagle@eyrie.org>
* Copyright 2016 Dropbox, Inc.
- * Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013,
- * 2014 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright 2002-2010, 2012-2014
+ * The Board of Trustees of the Leland Stanford Junior University
*
* See LICENSE for licensing terms.
*/
@@ -71,12 +72,14 @@ server_handle_io_event(struct bufferevent *bev, short events, void *data)
/*
* If we get ECONNRESET or EPIPE, the client went away without bothering
- * to read our data. This is the same as EOF except that we should also
- * stop trying to write data.
+ * to read our data. Stop trying to write data, but continue to read
+ * data, since we may otherwise miss output from the client before it went
+ * away.
*/
if (events & BEV_EVENT_ERROR)
if (socket_errno == ECONNRESET || socket_errno == EPIPE) {
- bufferevent_disable(bev, EV_READ | EV_WRITE);
+ debug("EPIPE or ECONNRESET from client");
+ bufferevent_disable(bev, EV_WRITE);
return;
}
@@ -161,7 +164,7 @@ start(evutil_socket_t junk UNUSED, short what UNUSED, void *data)
* actually runs the command. We have to use sockets rather than pipes
* because libevent's buffevents require sockets.
*
- * For protocol version one, we can use one socket pair for eerything,
+ * For protocol version one, we can use one socket pair for everything,
* since we don't distinguish between streams. For protocol version two,
* we use one socket pair for standard intput and standard output, and a
* separate read-only one for standard error so that we can keep the