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.
diff --git a/src/listener.c b/src/listener.c
index f63f9ba..7c21b9d 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -77,14 +77,16 @@
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 @@
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;