From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KLfGb-0007W5-Rt for qemu-devel@nongnu.org; Wed, 23 Jul 2008 10:24:33 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KLfGb-0007V5-4h for qemu-devel@nongnu.org; Wed, 23 Jul 2008 10:24:33 -0400 Received: from [199.232.76.173] (port=53130 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KLfGa-0007Us-Oi for qemu-devel@nongnu.org; Wed, 23 Jul 2008 10:24:32 -0400 Received: from mx1.redhat.com ([66.187.233.31]:58764) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KLfGa-0000Gs-FQ for qemu-devel@nongnu.org; Wed, 23 Jul 2008 10:24:32 -0400 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id m6NEOV9K005868 for ; Wed, 23 Jul 2008 10:24:31 -0400 Message-ID: <48873F17.4030101@redhat.com> Date: Wed, 23 Jul 2008 16:24:23 +0200 From: Gerd Hoffmann MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH 2/3] Always use nonblocking mode for qemu_chr_open_fd. References: <488688E3.105@codemonkey.ws> <20080723082413.GA2291@redhat.com> <48871A7E.5030501@redhat.com> <20080723121510.GJ2291@redhat.com> <48872979.4050107@redhat.com> In-Reply-To: <48872979.4050107@redhat.com> Content-Type: multipart/mixed; boundary="------------000102020403060407070009" Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "Daniel P. Berrange" Cc: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------000102020403060407070009 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit 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/ --------------000102020403060407070009 Content-Type: text/x-patch; name="qemu-pty.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="qemu-pty.diff" 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, --------------000102020403060407070009--