From b3fb60bdcd15cd3bd925a6423f40498f4a695043 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 4 Oct 2012 08:56:31 +0200 Subject: [PATCH] BUG/MEDIUM: listener: don't pause protocols that do not support it Pausing a UNIX_STREAM socket results in a major pain because the socket does not correctly resume, it wakes poll() but return EAGAIN on accept(), resulting in a busy loop. So let's only pause protocols that support it. This issues has existed since UNIX sockets were introduced on bind lines. --- src/listener.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/listener.c b/src/listener.c index f63f9bae3..7c21b9db2 100644 --- a/src/listener.c +++ b/src/listener.c @@ -77,14 +77,16 @@ int pause_listener(struct listener *l) if (l->state <= LI_PAUSED) return 1; - if (shutdown(l->fd, SHUT_WR) != 0) - return 0; /* Solaris dies here */ + if (l->proto->sock_prot == IPPROTO_TCP) { + if (shutdown(l->fd, SHUT_WR) != 0) + return 0; /* Solaris dies here */ - if (listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0) - return 0; /* OpenBSD dies here */ + if (listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0) + return 0; /* OpenBSD dies here */ - if (shutdown(l->fd, SHUT_RD) != 0) - return 0; /* should always be OK */ + if (shutdown(l->fd, SHUT_RD) != 0) + return 0; /* should always be OK */ + } if (l->state == LI_LIMITED) LIST_DEL(&l->wait_queue); @@ -104,7 +106,8 @@ int resume_listener(struct listener *l) if (l->state < LI_PAUSED) return 0; - if (l->state == LI_PAUSED && + if (l->proto->sock_prot == IPPROTO_TCP && + l->state == LI_PAUSED && listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0) return 0;