aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2016-01-19 14:13:29 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2016-02-09 15:45:26 +0100
commit34689e206abddac87a5217d458534e24f2a05562 (patch)
tree737d508f9eda56012b9d224775ae93ca320fd613
parent5b82b703b69acc67b78b98a5efc897a3912719eb (diff)
qemu-char: Keep pty slave file descriptor open until the master is closed
If a process opens the slave pts device, writes data to it, then immediately closes it, the data doesn't reliably get delivered to the emulated serial port. This seems to be because a read of the master pty device returns EIO on Linux if no process has the pts device open, even when data is waiting "in the pipe". A fix seems to be for QEMU to keep the pts file descriptor open until the pty is closed, as per the below patch. Signed-off-by: Ashley Jonathan <jonathan.ashley@altran.com> Message-Id: <AC19797808C8D548ABDE0CA4A97AA30A30DEB409@XMB-DCFR-37.europe.corp.altran.com> Reviewed-by: Michael Tokarev <mjt@tls.msk.ru> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--qemu-char.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/qemu-char.c b/qemu-char.c
index 927c47e503..1fbccf02ac 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1171,6 +1171,7 @@ typedef struct {
int connected;
guint timer_tag;
guint open_tag;
+ int slave_fd;
} PtyCharDriver;
static void pty_chr_update_read_handler_locked(CharDriverState *chr);
@@ -1347,6 +1348,7 @@ static void pty_chr_close(struct CharDriverState *chr)
qemu_mutex_lock(&chr->chr_write_lock);
pty_chr_state(chr, 0);
+ close(s->slave_fd);
object_unref(OBJECT(s->ioc));
if (s->timer_tag) {
g_source_remove(s->timer_tag);
@@ -1374,7 +1376,6 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
return NULL;
}
- close(slave_fd);
qemu_set_nonblock(master_fd);
chr = qemu_chr_alloc(common, errp);
@@ -1399,6 +1400,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
chr->explicit_be_open = true;
s->ioc = QIO_CHANNEL(qio_channel_file_new_fd(master_fd));
+ s->slave_fd = slave_fd;
s->timer_tag = 0;
return chr;