From a48e897f26c041f53802fe6d90bb3d8eb2bb7c07 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 18 Oct 2018 18:04:31 +0100 Subject: [PATCH] uxpty: support SS_EOF, when in pipe mode. If the child process's standard input is provided by a pipe that's separate from its output channels, we can - and should - honour a request to cause that process to receive input EOF, by closing the output end of that pipe. As usual, we do this by setting a pending-EOF flag and calling try_write, to ensure that any buffered output data is sent before the pipe actually closes. --- unix/uxpty.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/unix/uxpty.c b/unix/uxpty.c index dea208f7..d0fc2798 100644 --- a/unix/uxpty.c +++ b/unix/uxpty.c @@ -90,6 +90,7 @@ struct Pty { int child_dead, finished; int exit_code; bufchain output_data; + int pending_eof; Backend backend; }; @@ -1316,6 +1317,17 @@ static void pty_try_write(Pty *pty) bufchain_consume(&pty->output_data, ret); } + if (pty->pending_eof && bufchain_size(&pty->output_data) == 0) { + /* This should only happen if pty->master_i is a pipe that + * doesn't alias either output fd */ + assert(pty->master_i != pty->master_o); + assert(pty->master_i != pty->master_e); + uxsel_del(pty->master_i); + close(pty->master_i); + pty->master_i = -1; + pty->pending_eof = FALSE; + } + pty_uxsel_setup(pty); } @@ -1326,7 +1338,7 @@ static int pty_send(Backend *be, const char *buf, int len) { Pty *pty = container_of(be, Pty, backend); - if (pty->master_i < 0) + if (pty->master_i < 0 || pty->pending_eof) return 0; /* ignore all writes if fd closed */ bufchain_add(&pty->output_data, buf, len); @@ -1411,6 +1423,14 @@ static void pty_special(Backend *be, SessionSpecialCode code, int arg) return; } + if (code == SS_EOF) { + if (pty->master_i >= 0 && pty->master_i != pty->master_fd) { + pty->pending_eof = TRUE; + pty_try_write(pty); + } + return; + } + { int sig = -1;