]> xenbits.xensource.com Git - libvirt.git/commitdiff
lxc_controller.c: don't ignore failed "accept"
authorJim Meyering <meyering@redhat.com>
Thu, 20 May 2010 12:30:36 +0000 (14:30 +0200)
committerJim Meyering <meyering@redhat.com>
Thu, 20 May 2010 17:12:39 +0000 (19:12 +0200)
* src/lxc/lxc_controller.c (ignorable_epoll_accept_errno): New function.
(lxcControllerMain): Handle a failed accept carefully:
most errno values indicate legitimate failure and must be fatal.
However, ignore a special case: that in which an incoming client quits
between the poll() indicating its presence, and our accept() which
is trying to process it.

src/lxc/lxc_controller.c

index 1732780c1a732af8a92054ea6b62ff9fe1f4c045..23fda7f763ba1653666f56b38d91a64805a36320 100644 (file)
@@ -269,6 +269,17 @@ typedef struct _lxcTtyForwardFd_t {
     int active;
 } lxcTtyForwardFd_t;
 
+/* Return true if it is ok to ignore an accept-after-epoll syscall
+   that fails with the specified errno value.  Else false.  */
+static bool
+ignorable_epoll_accept_errno(int errnum)
+{
+  return (errnum == EINVAL
+          || errnum == ECONNABORTED
+          || errnum == EAGAIN
+          || errnum == EWOULDBLOCK);
+}
+
 /**
  * lxcControllerMain
  * @monitor: server socket fd to accept client requests
@@ -350,6 +361,18 @@ static int lxcControllerMain(int monitor,
         if (numEvents > 0) {
             if (epollEvent.data.fd == monitor) {
                 int fd = accept(monitor, NULL, 0);
+                if (fd < 0) {
+                    /* First reflex may be simply to declare accept failure
+                       to be a fatal error.  However, accept may fail when
+                       a client quits between the above epoll_wait and here.
+                       That case is not fatal, but rather to be expected,
+                       if not common, so ignore it.  */
+                    if (ignorable_epoll_accept_errno(errno))
+                        continue;
+                    virReportSystemError(errno, "%s",
+                                         _("accept(monitor,...) failed"));
+                    goto cleanup;
+                }
                 if (client != -1) { /* Already connected, so kick new one out */
                     close(fd);
                     continue;