qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: "Daniel P. Berrange" <berrange@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 2/3] Always use nonblocking mode for	qemu_chr_open_fd.
Date: Wed, 23 Jul 2008 16:24:23 +0200	[thread overview]
Message-ID: <48873F17.4030101@redhat.com> (raw)
In-Reply-To: <48872979.4050107@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 215 bytes --]

  Hi,

> Which means we need our own code for ptys and can't use the generic fd
> functions.  I'll go trying cooking up a patch ...

Comments on this one?

cheers,
  Gerd

-- 
http://kraxel.fedorapeople.org/xenner/

[-- Attachment #2: qemu-pty.diff --]
[-- Type: text/x-patch, Size: 4062 bytes --]

diff --git a/vl.c b/vl.c
index 1af6d10..23d92e5 100644
--- a/vl.c
+++ b/vl.c
@@ -2454,21 +2454,153 @@ void cfmakeraw (struct termios *termios_p)
 #endif
 
 #if defined(__linux__) || defined(__sun__)
+
+typedef struct {
+    int fd;
+    int connected;
+    int polling;
+    int read_bytes;
+    int interval;
+    QEMUTimer *timer;
+} PtyCharDriver;
+
+static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    PtyCharDriver *s = chr->opaque;
+    if (!s->connected)
+	return 0;
+    return unix_write(s->fd, buf, len);
+}
+
+static void pty_chr_state(CharDriverState *chr, int connected)
+{
+    PtyCharDriver *s = chr->opaque;
+
+    if (s->connected == connected)
+	return;
+    if (connected) {
+	fprintf(stderr,"%s: %s connected\n", __FUNCTION__, ptsname(s->fd));
+	s->connected = 1;
+	qemu_chr_reset(chr);
+    } else {
+	fprintf(stderr,"%s: %s disconnected\n", __FUNCTION__, ptsname(s->fd));
+	s->connected = 0;
+	qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + s->interval);
+    }
+}
+
+static int pty_chr_read_poll(void *opaque)
+{
+    CharDriverState *chr = opaque;
+    PtyCharDriver *s = chr->opaque;
+
+    s->read_bytes = qemu_chr_can_read(chr);
+    return s->read_bytes;
+}
+
+static void pty_chr_read(void *opaque)
+{
+    CharDriverState *chr = opaque;
+    PtyCharDriver *s = chr->opaque;
+    int size, len;
+    uint8_t buf[1024];
+
+    len = sizeof(buf);
+    if (len > s->read_bytes)
+        len = s->read_bytes;
+    if (len == 0)
+        return;
+    size = read(s->fd, buf, len);
+    if ((size == -1 && EIO == errno) ||
+	(size == 0)) {
+	qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+	s->polling = 0;
+	pty_chr_state(chr, 0);
+        return;
+    }
+    if (size > 0) {
+	pty_chr_state(chr, 1);
+        qemu_chr_read(chr, buf, size);
+    }
+}
+
+static void pty_chr_update_read_handler(CharDriverState *chr)
+{
+    PtyCharDriver *s = chr->opaque;
+
+    qemu_set_fd_handler2(s->fd, pty_chr_read_poll,
+			 pty_chr_read, NULL, chr);
+    s->polling = 1;
+    qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + s->interval);
+}
+
+void pty_chr_timer(void *opaque)
+{
+    struct CharDriverState *chr = opaque;    
+    PtyCharDriver *s = chr->opaque;
+
+    if (s->connected) {
+	/* All fine, nothing to do. */
+	return;
+    }
+    if (s->polling) {
+	/* Ran for a while without getting EIO for reads,
+	 * probably someone connected to the slave pty. */
+	pty_chr_state(chr, 1);
+	return;
+    }
+    /* Try reading again ... */
+#if 0
+    fprintf(stderr,"%s: %s checking ...\n", __FUNCTION__, ptsname(s->fd));
+#endif
+    pty_chr_update_read_handler(chr);
+}
+
+static void pty_chr_close(struct CharDriverState *chr)
+{
+    PtyCharDriver *s = chr->opaque;
+
+    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+    close(s->fd);
+    qemu_free(s);
+}
+
 static CharDriverState *qemu_chr_open_pty(void)
 {
+    CharDriverState *chr;
+    PtyCharDriver *s;
     struct termios tty;
-    int master_fd, slave_fd;
+    int slave_fd;
+    
+    chr = qemu_mallocz(sizeof(CharDriverState));
+    if (!chr)
+        return NULL;
+    s = qemu_mallocz(sizeof(PtyCharDriver));
+    if (!s) {
+        free(chr);
+        return NULL;
+    }
 
-    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) < 0) {
+    if (openpty(&s->fd, &slave_fd, NULL, NULL, NULL) < 0) {
         return NULL;
     }
 
     /* Set raw attributes on the pty. */
     cfmakeraw(&tty);
     tcsetattr(slave_fd, TCSAFLUSH, &tty);
+    close(slave_fd);
+    
+    fprintf(stderr, "char device redirected to %s\n", ptsname(s->fd));
+    
+    chr->opaque = s;
+    chr->chr_write = pty_chr_write;
+    chr->chr_update_read_handler = pty_chr_update_read_handler;
+    chr->chr_close = pty_chr_close;
 
-    fprintf(stderr, "char device redirected to %s\n", ptsname(master_fd));
-    return qemu_chr_open_fd(master_fd, master_fd);
+    s->interval = 100; /* miliseconds */
+    s->timer = qemu_new_timer(rt_clock, pty_chr_timer, chr);
+    
+    return chr;
 }
 
 static void tty_serial_init(int fd, int speed,

  parent reply	other threads:[~2008-07-23 14:24 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-18 13:24 [Qemu-devel] [PATCH 2/3] Always use nonblocking mode for qemu_chr_open_fd Ian Jackson
2008-07-23  1:26 ` Anthony Liguori
2008-07-23  8:24   ` Daniel P. Berrange
2008-07-23 11:48     ` Gerd Hoffmann
2008-07-23 12:15       ` Daniel P. Berrange
2008-07-23 12:52         ` Gerd Hoffmann
2008-07-23 12:59           ` Daniel P. Berrange
2008-07-23 14:24           ` Gerd Hoffmann [this message]
2008-07-23 15:24             ` Anthony Liguori
2008-07-23 15:31               ` Daniel P. Berrange
2008-07-23 15:32                 ` Anthony Liguori
2008-07-23 16:17                   ` Gerd Hoffmann
2008-07-23 16:33                     ` Anthony Liguori
2008-07-23 19:08                       ` Jamie Lokier
2008-07-24  7:24                         ` Gerd Hoffmann
2008-07-24  7:54                       ` Gerd Hoffmann
2008-07-24  8:31                         ` Daniel P. Berrange
2008-07-24  9:24                         ` Jamie Lokier
2008-07-24  9:33                           ` Samuel Thibault
2008-07-24 11:18                             ` Gerd Hoffmann
2008-07-23 16:11               ` Gerd Hoffmann
2008-07-23 16:31                 ` Anthony Liguori
2008-07-24  8:35                   ` Daniel P. Berrange
2008-07-24 14:23                     ` Anthony Liguori
2008-07-24 15:07                       ` Jamie Lokier
2008-07-24 14:53                         ` Gerd Hoffmann
2008-07-23 16:44                 ` Paul Brook
2008-07-24 17:37                   ` Anthony Liguori
2008-07-25  7:15                   ` Gerd Hoffmann
2008-07-25 16:17                     ` Jamie Lokier
2008-07-28  8:49                       ` Gerd Hoffmann
2008-07-28 11:59                         ` Jamie Lokier
2008-07-28 12:20                           ` Gerd Hoffmann
2017-02-01 12:33                             ` David Woodhouse
2008-07-24 15:37             ` [Qemu-devel] " Anthony Liguori
2008-07-25 11:42               ` Gerd Hoffmann
2008-07-25 15:04                 ` Anthony Liguori
2008-07-28  9:59                   ` Gerd Hoffmann
2008-07-28 18:55                     ` Anthony Liguori
2008-07-23  9:34   ` [Qemu-devel] " Kevin Wolf
2008-07-23 10:17     ` Ian Jackson
2008-07-23 11:43       ` Kevin Wolf
2008-07-23 12:04     ` Gerd Hoffmann
2008-07-23 12:18       ` Paul Brook

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=48873F17.4030101@redhat.com \
    --to=kraxel@redhat.com \
    --cc=berrange@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).