lxc_controller.c: don't ignore failed "accept"

* 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.
This commit is contained in:
Jim Meyering 2010-05-20 14:30:36 +02:00
parent 348c6fc0ab
commit 1f6fc519cd

View 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;