qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: Gerd Hoffmann <kraxel@redhat.com>
Cc: qemu-devel@nongnu.org, Paul Brook <paul@codesourcery.com>
Subject: [Qemu-devel] Re: [PATCH 2/3] Always use nonblocking mode for qemu_chr_open_fd.
Date: Fri, 25 Jul 2008 10:04:25 -0500	[thread overview]
Message-ID: <4889EB79.80903@codemonkey.ws> (raw)
In-Reply-To: <4889BC1D.1030305@redhat.com>

Gerd Hoffmann wrote:
> From 076b5cff55b57a64e5f8daf32186d924945f78b4 Mon Sep 17 00:00:00 2001
> From: Gerd Hoffmann <kraxel@redhat.com>
> Date: Wed, 23 Jul 2008 16:35:40 +0200
> Subject: [PATCH 03/21] Attempt to detect unconnected ptys.
>
> This patch moves the pty char device imlementation away from the generic
> filehandle code.  It tries to detect as good as possible whenever there
> is someone connected to the slave pty device and only send data down the
> road in case someone is listening.  Unfortunaly we have to poll via
> timer once in a while to check the status because we have to use read()
> on the master pty to figure the status (returns -EIO when unconnected).
>
> Poll intervall for an idle guest is one second, when the guest sends
> data to the virtual device linked to the pty we check more frequently.
>
> The point for all of this is to avoid qemu blocking and not responding
> any more.  Writing to the master pty handle succeeds even when nobody is
> connected to (and reading from) to the slave end of the pty.  The kernel
> just bufferes the writes.  And as soon as the kernel buffer is full the
> write() call blocks forever ...
>   

You've got whitespace damage.  You're mixing tabs and spaces.  Please 
only use spaces.

> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  vl.c |  158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 files changed, 154 insertions(+), 4 deletions(-)
>
> diff --git a/vl.c b/vl.c
> index 23b5243..faf7b95 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2474,21 +2474,171 @@ void cfmakeraw (struct termios *termios_p)
>  #endif
>  
>  #if defined(__linux__) || defined(__sun__)
> +
> +typedef struct {
> +    int fd;
> +    int connected;
> +    int polling;
> +    int read_bytes;
> +    QEMUTimer *timer;
> +} PtyCharDriver;
> +
> +static void pty_chr_update_read_handler(CharDriverState *chr);
> +static void pty_chr_state(CharDriverState *chr, int connected);
> +
> +static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
> +{
> +    PtyCharDriver *s = chr->opaque;
> +
> +    if (!s->connected) {
> +	/* guest sends data, check for (re-)connect */
> +	pty_chr_update_read_handler(chr);
> +	return 0;
> +    }
> +    return unix_write(s->fd, buf, len);
> +}
> +
> +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)) {
>   

errno == EIO

> +	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;
> +    /*
> +     * Short timeout here: just need wait long enougth that qemu makes
> +     * it through the poll loop once.  When reconnected we want a
> +     * short timeout so we notice it almost instantly.  Otherwise
> +     * read() gives us -EIO instantly, making pty_chr_state() reset the
> +     * timeout to the normal (much longer) poll interval before the
> +     * timer triggers.
> +     */
> +    qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 10);
>   

Perhaps what you really want here is a bottom half?

> +}
> +
> +static void pty_chr_state(CharDriverState *chr, int connected)
> +{
> +    PtyCharDriver *s = chr->opaque;
> +
> +    if (!connected) {
> +	if (s->connected) {
> +	    fprintf(stderr,"%s: %s disconnected\n", __FUNCTION__, ptsname(s->fd));
>   

Obviously this debugging has to go.

> +	    s->connected = 0;
> +	}
> +	/* (re-)connect poll interval for idle guests: once per second.
> +	 * We check more frequently in case the guests sends data to
> +	 * the virtual device linked to our pty. */
> +	qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000);
> +    } else {
> +	if (!s->connected) {
> +	    fprintf(stderr,"%s: %s connected\n", __FUNCTION__, ptsname(s->fd));
> +	    s->connected = 1;
> +	    qemu_chr_reset(chr);
> +	}
> +    }
> +}
> +
> +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);
>   

qemu_free()

Regards,

Anthony Liguori

> +        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->timer = qemu_new_timer(rt_clock, pty_chr_timer, chr);
> +    
> +    return chr;
>  }
>  
>  static void tty_serial_init(int fd, int speed,
> -- 1.5.4.1

  reply	other threads:[~2008-07-25 15:05 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
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 [this message]
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=4889EB79.80903@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=kraxel@redhat.com \
    --cc=paul@codesourcery.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).