From c9a43f66edfc8dea94db4c2d0f05e13f75434282 Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Sat, 25 Aug 2012 01:14:16 +0200 Subject: [PATCH] dom0/qrexec: do not exit client before all data in both direction transfered When qrexec_client cannot write to its stdout, this doesn't necessary mean that there is no data in opposite direction. Simple example is RPC service: when process in destination VM closes its stdin, it can still send some data to triggering VM. --- qrexec/qrexec_client.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/qrexec/qrexec_client.c b/qrexec/qrexec_client.c index 4065e6b0..cb47042f 100644 --- a/qrexec/qrexec_client.c +++ b/qrexec/qrexec_client.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "qrexec.h" #include "buffer.h" #include "glue.h" @@ -108,6 +109,10 @@ void handle_input(int s) if (ret == 0) { local_stdout_fd = -1; shutdown(s, SHUT_WR); + if (local_stdin_fd == -1) { + // if pipe in opposite direction already closed, no need to stay alive + do_exit(0); + } } if (!write_all(s, buf, ret)) { perror("write daemon"); @@ -136,11 +141,20 @@ void handle_daemon_data(int s) switch (hdr.type) { case MSG_SERVER_TO_CLIENT_STDOUT: - if (hdr.len == 0) + if (local_stdin_fd == -1) + break; + if (hdr.len == 0) { close(local_stdin_fd); - else if (!write_all(local_stdin_fd, buf, hdr.len)) { - perror("write local stdout"); - do_exit(1); + local_stdin_fd = -1; + } else if (!write_all(local_stdin_fd, buf, hdr.len)) { + if (errno == EPIPE) { + // remote side have closed its stdin, handle data in oposite + // direction (if any) before exit + local_stdin_fd = -1; + } else { + perror("write local stdout"); + do_exit(1); + } } break; case MSG_SERVER_TO_CLIENT_STDERR: