1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
From f3d75364fbebf2ddb6393e54db5e10b6f6234e14 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 18 Apr 2019 15:13:54 +0200
Subject: [PATCH] socket-util: make sure flush_accept() doesn't hang on
unexpected EOPNOTSUPP
So apparently there are two reasons why accept() can return EOPNOTSUPP:
because the socket is not a listening stream socket (or similar), or
because the incoming TCP connection for some reason wasn't acceptable to
the host. THe latter should be a transient error, as suggested on
accept(2). The former however should be considered fatal for
flush_accept(). Let's fix this by explicitly checking whether the socket
is a listening socket beforehand.
---
src/basic/socket-util.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 904bafb76f9..e787d53d8f4 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -1225,9 +1225,22 @@ int flush_accept(int fd) {
.fd = fd,
.events = POLLIN,
};
- int r;
+ int r, b;
+ socklen_t l = sizeof(b);
+
+ /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately
+ * closing them. */
+
+ if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0)
+ return -errno;
- /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
+ assert(l == sizeof(b));
+ if (!b) /* Let's check if this is a socket accepting connections before calling accept(). That's
+ * because accept4() can return EOPNOTSUPP in the fd we are called on is not a listening
+ * socket, or in case the incoming TCP connection transiently triggered that (see accept(2)
+ * man page for details). The latter case is a transient error we should continue looping
+ * on. The former case however is fatal. */
+ return -ENOTTY;
for (;;) {
int cfd;
|