[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] Fix xenconsole's "Could not read tty from store"
Any conclusion on this one, before I do a second release candidate for 3.2.0? -- Keir On 18/12/07 18:52, "John Levon" <levon@xxxxxxxxxxxxxxxxx> wrote: > On Tue, Dec 18, 2007 at 06:18:16PM +0000, Samuel Thibault wrote: > >> To my understanding, from the server side tcsetattr should only be >> performed on the master side (with effect on the slave side too). > > Here's another try, what does this do on Linux? My test program works > without needing the tcsetattr, as does xenconsoled > > thanks > john > > > # HG changeset patch > # User john.levon@xxxxxxx > # Date 1198003657 28800 > # Node ID 6f03f4ec458d4780314c015da214795b7b1cf195 > # Parent 539cbabd97b5ff3d335de151636040bb2f4cd629 > Fix master/slave handling in xenconsoled > > Fix a number of problems with the pty handling: > > - make openpty() implementation work on Solaris > - set raw on the slave fd, not the master, as the master doesn't > have a line discipline pushed on Solaris > - make sure we don't leak the slave fd returned from openpty() > - don't use the 'name' argument of openpty() as it's a security risk > - note behaviour of a zero read of the master on Solaris > - remove pointless tcget/setattr > > Signed-off-by: John Levon <john.levon@xxxxxxx> > Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxx> > > diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c > --- a/tools/console/daemon/io.c > +++ b/tools/console/daemon/io.c > @@ -36,10 +36,14 @@ > #include <stdarg.h> > #include <sys/mman.h> > #include <sys/time.h> > +#include <assert.h> > #if defined(__NetBSD__) || defined(__OpenBSD__) > #include <util.h> > #elif defined(__linux__) || defined(__Linux__) > #include <pty.h> > +#endif > +#if defined(__sun__) > +#include <stropts.h> > #endif > > #define MAX(a, b) (((a) > (b)) ? (a) : (b)) > @@ -75,7 +79,8 @@ struct domain > struct domain > { > int domid; > - int tty_fd; > + int master_fd; > + int slave_fd; > int log_fd; > bool is_dead; > struct buffer buffer; > @@ -227,77 +232,90 @@ static int create_domain_log(struct doma > return fd; > } > > +static void domain_close_tty(struct domain *dom) > +{ > + if (dom->master_fd != -1) { > + close(dom->master_fd); > + dom->master_fd = -1; > + } > + > + if (dom->slave_fd != -1) { > + close(dom->slave_fd); > + dom->slave_fd = -1; > + } > +} > + > #ifdef __sun__ > /* Once Solaris has openpty(), this is going to be removed. */ > -int openpty(int *amaster, int *aslave, char *name, > - struct termios *termp, struct winsize *winp) > +static int openpty(int *amaster, int *aslave, char *name, > + struct termios *termp, struct winsize *winp) > { > - int mfd, sfd; > + const char *slave; > + int mfd = -1, sfd = -1; > > *amaster = *aslave = -1; > - mfd = sfd = -1; > > mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY); > if (mfd < 0) > - goto err0; > + goto err; > > if (grantpt(mfd) == -1 || unlockpt(mfd) == -1) > - goto err1; > + goto err; > > - /* This does not match openpty specification, > - * but as long as this does not hurt, this is acceptable. > - */ > - mfd = sfd; > + if ((slave = ptsname(mfd)) == NULL) > + goto err; > > - if (termp != NULL && tcgetattr(sfd, termp) < 0) > - goto err1; > + if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1) > + goto err; > + > + if (ioctl(sfd, I_PUSH, "ptem") == -1) > + goto err; > > if (amaster) > *amaster = mfd; > if (aslave) > *aslave = sfd; > - if (name) > - strlcpy(name, ptsname(mfd), sizeof(slave)); > if (winp) > ioctl(sfd, TIOCSWINSZ, winp); > > + assert(name == NULL); > + assert(termp == NULL); > + > return 0; > > -err1: > +err: > + if (sfd != -1) > + close(sfd); > close(mfd); > -err0: > return -1; > } > #endif > > - > static int domain_create_tty(struct domain *dom) > { > - char slave[80]; > - struct termios term; > + const char *slave; > char *path; > - int master, slavefd; > int err; > bool success; > char *data; > unsigned int len; > > - if (openpty(&master, &slavefd, slave, &term, NULL) < 0) { > - master = -1; > + assert(dom->slave_fd == -1); > + assert(dom->master_fd == -1); > + > + if (openpty(&dom->master_fd, &dom->slave_fd, NULL, NULL, NULL) < 0) { > err = errno; > dolog(LOG_ERR, "Failed to create tty for domain-%d (errno = %i, %s)", > dom->domid, err, strerror(err)); > - return master; > + return 0; > } > > - cfmakeraw(&term); > - if (tcsetattr(master, TCSAFLUSH, &term) < 0) { > + if ((slave = ptsname(dom->master_fd)) == NULL) { > err = errno; > - dolog(LOG_ERR, "Failed to set tty attribute for domain-%d (errno = %i, > %s)", > + dolog(LOG_ERR, "Failed to get slave name for domain-%d (errno = %i, %s)", > dom->domid, err, strerror(err)); > goto out; > } > - > > if (dom->use_consolepath) { > success = asprintf(&path, "%s/limit", dom->conspath) != > @@ -340,15 +358,15 @@ static int domain_create_tty(struct doma > goto out; > } > > - if (fcntl(master, F_SETFL, O_NONBLOCK) == -1) > + if (fcntl(dom->master_fd, F_SETFL, O_NONBLOCK) == -1) > goto out; > > - return master; > - out: > - close(master); > - return -1; > + return 1; > +out: > + domain_close_tty(dom); > + return 0; > } > - > + > /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ > int xs_gather(struct xs_handle *xs, const char *dir, ...) > { > @@ -454,10 +472,8 @@ static int domain_create_ring(struct dom > dom->local_port = rc; > dom->remote_port = remote_port; > > - if (dom->tty_fd == -1) { > - dom->tty_fd = domain_create_tty(dom); > - > - if (dom->tty_fd == -1) { > + if (dom->master_fd == -1) { > + if (!domain_create_tty(dom)) { > err = errno; > xc_evtchn_close(dom->xce_handle); > dom->xce_handle = -1; > @@ -535,7 +551,8 @@ static struct domain *create_domain(int > dom->conspath = s; > strcat(dom->conspath, "/console"); > > - dom->tty_fd = -1; > + dom->master_fd = -1; > + dom->slave_fd = -1; > dom->log_fd = -1; > > dom->is_dead = false; > @@ -597,14 +614,7 @@ static void remove_domain(struct domain > > static void cleanup_domain(struct domain *d) > { > - if (d->tty_fd != -1) { > - close(d->tty_fd); > - d->tty_fd = -1; > - } > - if (d->log_fd != -1) { > - close(d->log_fd); > - d->log_fd = -1; > - } > + domain_close_tty(d); > > free(d->buffer.data); > d->buffer.data = NULL; > @@ -683,13 +693,17 @@ static void handle_tty_read(struct domai > if (len > sizeof(msg)) > len = sizeof(msg); > > - len = read(dom->tty_fd, msg, len); > - if (len < 1) { > - close(dom->tty_fd); > - dom->tty_fd = -1; > + len = read(dom->master_fd, msg, len); > + /* > + * Note: on Solaris, len == 0 means the slave closed, and this > + * is no problem, but Linux can't handle this usefully, so we > + * keep the slave open for the duration. > + */ > + if (len < 0) { > + domain_close_tty(dom); > > if (domain_is_valid(dom->domid)) { > - dom->tty_fd = domain_create_tty(dom); > + domain_create_tty(dom); > } else { > shutdown_domain(dom); > } > @@ -703,8 +717,7 @@ static void handle_tty_read(struct domai > intf->in_prod = prod; > xc_evtchn_notify(dom->xce_handle, dom->local_port); > } else { > - close(dom->tty_fd); > - dom->tty_fd = -1; > + domain_close_tty(dom); > shutdown_domain(dom); > } > } > @@ -716,17 +729,16 @@ static void handle_tty_write(struct doma > if (dom->is_dead) > return; > > - len = write(dom->tty_fd, dom->buffer.data + dom->buffer.consumed, > + len = write(dom->master_fd, dom->buffer.data + dom->buffer.consumed, > dom->buffer.size - dom->buffer.consumed); > if (len < 1) { > dolog(LOG_DEBUG, "Write failed on domain %d: %zd, %d\n", > dom->domid, len, errno); > > - close(dom->tty_fd); > - dom->tty_fd = -1; > + domain_close_tty(dom); > > if (domain_is_valid(dom->domid)) { > - dom->tty_fd = domain_create_tty(dom); > + domain_create_tty(dom); > } else { > shutdown_domain(dom); > } > @@ -895,13 +907,13 @@ void handle_io(void) > max_fd = MAX(evtchn_fd, max_fd); > } > > - if (d->tty_fd != -1) { > + if (d->master_fd != -1) { > if (!d->is_dead && ring_free_bytes(d)) > - FD_SET(d->tty_fd, &readfds); > + FD_SET(d->master_fd, &readfds); > > if (!buffer_empty(&d->buffer)) > - FD_SET(d->tty_fd, &writefds); > - max_fd = MAX(d->tty_fd, max_fd); > + FD_SET(d->master_fd, &writefds); > + max_fd = MAX(d->master_fd, max_fd); > } > } > > @@ -951,10 +963,10 @@ void handle_io(void) > handle_ring_read(d); > } > > - if (d->tty_fd != -1 && FD_ISSET(d->tty_fd, &readfds)) > + if (d->master_fd != -1 && FD_ISSET(d->master_fd, &readfds)) > handle_tty_read(d); > > - if (d->tty_fd != -1 && FD_ISSET(d->tty_fd, &writefds)) > + if (d->master_fd != -1 && FD_ISSET(d->master_fd, &writefds)) > handle_tty_write(d); > > if (d->is_dead) > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxxxxxxxx > http://lists.xensource.com/xen-devel _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |