The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3427
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === In case the child simply dies or the client exits the fd will be closed and we will receive a POLLNVAL event. We need to handle this case otherwise we will keep poll()ing without ever exiting. Closes #2964. Signed-off-by: Christian Brauner <[email protected]>
From 32ae26b8b7ff03538ebb75e02488c0a23601ebc3 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Mon, 19 Jun 2017 15:44:43 +0200 Subject: [PATCH] exec: detect POLLNVAL when poll()ing In case the child simply dies or the client exits the fd will be closed and we will receive a POLLNVAL event. We need to handle this case otherwise we will keep poll()ing without ever exiting. Closes #2964. Signed-off-by: Christian Brauner <[email protected]> --- lxd/container_exec.go | 2 ++ shared/util_linux.go | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lxd/container_exec.go b/lxd/container_exec.go index 9c4359007..91d860e6a 100644 --- a/lxd/container_exec.go +++ b/lxd/container_exec.go @@ -227,10 +227,12 @@ func (s *execWs) Do(op *operation) error { conn := s.conns[0] s.connsLock.Unlock() + logger.Debugf("Starting to mirror websocket") readDone, writeDone := shared.WebsocketExecMirror(conn, ptys[0], ptys[0], attachedChildIsDead, int(ptys[0].Fd())) <-readDone <-writeDone + logger.Debugf("Finished to mirror websocket") conn.Close() wgEOF.Done() diff --git a/shared/util_linux.go b/shared/util_linux.go index 66e896139..5be541c6e 100644 --- a/shared/util_linux.go +++ b/shared/util_linux.go @@ -570,12 +570,14 @@ func ExecReaderToChannel(r io.Reader, bufferSize int, exited <-chan bool, fd int atomic.StoreInt32(&attachedChildIsDead, 1) - ret, revents, err := GetPollRevents(fd, 0, (POLLIN | POLLPRI | POLLERR | POLLHUP | POLLRDHUP)) + ret, revents, err := GetPollRevents(fd, 0, (POLLIN | POLLPRI | POLLERR | POLLHUP | POLLRDHUP | POLLNVAL)) if ret < 0 { logger.Errorf("Failed to poll(POLLIN | POLLPRI | POLLHUP | POLLRDHUP) on file descriptor: %s.", err) } else if ret > 0 { if (revents & POLLERR) > 0 { logger.Warnf("Detected poll(POLLERR) event.") + } else if (revents & POLLNVAL) > 0 { + logger.Warnf("Detected poll(POLLNVAL) event.") } } else if ret == 0 { logger.Debugf("No data in stdout: exiting.") @@ -595,7 +597,7 @@ func ExecReaderToChannel(r io.Reader, bufferSize int, exited <-chan bool, fd int nr := 0 var err error - ret, revents, err := GetPollRevents(fd, -1, (POLLIN | POLLPRI | POLLERR | POLLHUP | POLLRDHUP)) + ret, revents, err := GetPollRevents(fd, -1, (POLLIN | POLLPRI | POLLERR | POLLHUP | POLLRDHUP | POLLNVAL)) if ret < 0 { // This condition is only reached in cases where we are massively f*cked since we even handle // EINTR in the underlying C wrapper around poll(). So let's exit here. @@ -616,6 +618,9 @@ func ExecReaderToChannel(r io.Reader, bufferSize int, exited <-chan bool, fd int if (revents & POLLERR) > 0 { logger.Warnf("Detected poll(POLLERR) event: exiting.") return + } else if (revents & POLLNVAL) > 0 { + logger.Warnf("Detected poll(POLLNVAL) event: exiting.") + return } if ((revents & (POLLIN | POLLPRI)) > 0) && !both { @@ -671,11 +676,11 @@ func ExecReaderToChannel(r io.Reader, bufferSize int, exited <-chan bool, fd int // or (POLLHUP | POLLRDHUP). Both will trigger another codepath (See [2].) // that takes care that all data of the child that is buffered in // stdout is written out. - ret, revents, err := GetPollRevents(fd, 0, (POLLIN | POLLPRI | POLLERR | POLLHUP | POLLRDHUP)) + ret, revents, err := GetPollRevents(fd, 0, (POLLIN | POLLPRI | POLLERR | POLLHUP | POLLRDHUP | POLLNVAL)) if ret < 0 { logger.Errorf("Failed to poll(POLLIN | POLLPRI | POLLERR | POLLHUP | POLLRDHUP) on file descriptor: %s. Exiting.", err) return - } else if (revents & (POLLHUP | POLLRDHUP)) == 0 { + } else if (revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)) == 0 { logger.Debugf("Exiting but background processes are still running.") return }
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
