From 594da0a3e140b1801b5f85d2be930db834d1e9cc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Mar 2019 12:56:25 +0100 Subject: [PATCH 1/9] fd-util: beef up ERRNO_IS_xyz() macros a bit Let's implicit drop the negation if there is one, to simplify things a bit, similar how we do it in log_xyz()... --- src/basic/fd-util.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h index 4085a244d2..8c3daf62a8 100644 --- a/src/basic/fd-util.h +++ b/src/basic/fd-util.h @@ -81,13 +81,13 @@ int fd_duplicate_data_fd(int fd); /* The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. * See the icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */ #define ERRNO_IS_DISCONNECT(r) \ - IN_SET(r, \ + IN_SET(abs(r), \ ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \ ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, ENONET) /* Resource exhaustion, could be our fault or general system trouble */ #define ERRNO_IS_RESOURCE(r) \ - IN_SET(r, ENOMEM, EMFILE, ENFILE) + IN_SET(abs(r), ENOMEM, EMFILE, ENFILE) int fd_move_above_stdio(int fd); From c3fecddf0d0b2cebc313989fb11cad53aa03e37a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Mar 2019 13:00:29 +0100 Subject: [PATCH 2/9] util: move ERRNO_IS_xyz macros to errno-util.h It's where they fit much better. --- src/basic/errno-util.h | 13 +++++++++++++ src/basic/fd-util.h | 12 ------------ src/resolve/resolved-dns-transaction.c | 1 + 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h index 2d72b8ce9e..067b4fa303 100644 --- a/src/basic/errno-util.h +++ b/src/basic/errno-util.h @@ -27,3 +27,16 @@ static inline int negative_errno(void) { assert_return(errno > 0, -EINVAL); return -errno; } + +/* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5. + * + * Hint #2: The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. See the + * icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */ +#define ERRNO_IS_DISCONNECT(r) \ + IN_SET(abs(r), \ + ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \ + ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, ENONET) + +/* Resource exhaustion, could be our fault or general system trouble */ +#define ERRNO_IS_RESOURCE(r) \ + IN_SET(abs(r), ENOMEM, EMFILE, ENFILE) diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h index 8c3daf62a8..e490753caf 100644 --- a/src/basic/fd-util.h +++ b/src/basic/fd-util.h @@ -77,18 +77,6 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags); int fd_duplicate_data_fd(int fd); -/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */ -/* The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. - * See the icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */ -#define ERRNO_IS_DISCONNECT(r) \ - IN_SET(abs(r), \ - ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \ - ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, ENONET) - -/* Resource exhaustion, could be our fault or general system trouble */ -#define ERRNO_IS_RESOURCE(r) \ - IN_SET(abs(r), ENOMEM, EMFILE, ENFILE) - int fd_move_above_stdio(int fd); int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 425627d97f..9cac91f536 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -6,6 +6,7 @@ #include "alloc-util.h" #include "dns-domain.h" #include "errno-list.h" +#include "errno-util.h" #include "fd-util.h" #include "random-util.h" #include "resolved-dns-cache.h" From 4e17e5c2bf494323ff57ad3a09bf238de4fcc4db Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Mar 2019 13:02:21 +0100 Subject: [PATCH 3/9] stdio-bridge: use ERRNO_IS_DISCONNECT() to detect disconnects Let's use the macro we already have to make this safer. Moreover log about all other errors. --- src/stdio-bridge/stdio-bridge.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c index 7060897ab7..1767515e3e 100644 --- a/src/stdio-bridge/stdio-bridge.c +++ b/src/stdio-bridge/stdio-bridge.c @@ -14,6 +14,7 @@ #include "build.h" #include "bus-internal.h" #include "bus-util.h" +#include "errno-util.h" #include "log.h" #include "main-func.h" #include "util.h" @@ -187,9 +188,13 @@ static int run(int argc, char *argv[]) { continue; r = sd_bus_process(b, &m); - if (r < 0) + if (r < 0) { /* treat 'connection reset by peer' as clean exit condition */ - return r == -ECONNRESET ? 0 : r; + if (ERRNO_IS_DISCONNECT(r)) + return 0; + + return log_error_errno(r, "Failed to process bus: %m"); + } if (m) { r = sd_bus_send(a, m, NULL); From 578e95de48b8f9178be73beb207df29b147d2e0e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Mar 2019 13:03:18 +0100 Subject: [PATCH 4/9] stdio-bridge: fix getopt() parameter list to match reality --- src/stdio-bridge/stdio-bridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c index 1767515e3e..8022d3e596 100644 --- a/src/stdio-bridge/stdio-bridge.c +++ b/src/stdio-bridge/stdio-bridge.c @@ -57,7 +57,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hsup:", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hp:M:", options, NULL)) >= 0) { switch (c) { From b6056ea37cda628c2053aa3554ac32502b5223ff Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Mar 2019 13:03:49 +0100 Subject: [PATCH 5/9] stdio-bridge: tweak getopt() case statement a bit --- src/stdio-bridge/stdio-bridge.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c index 8022d3e596..323191def6 100644 --- a/src/stdio-bridge/stdio-bridge.c +++ b/src/stdio-bridge/stdio-bridge.c @@ -62,26 +62,23 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { case 'h': - help(); - return 0; + return help(); case ARG_VERSION: return version(); - case '?': - return -EINVAL; - case 'p': arg_bus_path = optarg; - break; case 'M': arg_bus_path = optarg; - arg_transport = BUS_TRANSPORT_MACHINE; - break; + + case '?': + return -EINVAL; + default: return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown option code %c", c); From 451e16e0cb56035b01de7d9559eba91247003681 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Mar 2019 13:04:05 +0100 Subject: [PATCH 6/9] stdio-bridge: use SYNTHETIC_ERRNO() where appropriate --- src/stdio-bridge/stdio-bridge.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c index 323191def6..16f4bdb809 100644 --- a/src/stdio-bridge/stdio-bridge.c +++ b/src/stdio-bridge/stdio-bridge.c @@ -109,10 +109,8 @@ static int run(int argc, char *argv[]) { } else if (r == 1) { in_fd = SD_LISTEN_FDS_START; out_fd = SD_LISTEN_FDS_START; - } else { - log_error("Illegal number of file descriptors passed."); - return -EINVAL; - } + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Illegal number of file descriptors passed."); is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 && From d1ded478ee3db6e98491df6e2442efc7f628e76d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Mar 2019 13:04:21 +0100 Subject: [PATCH 7/9] stdio-bridge: slightly optimize formatting of structure --- src/stdio-bridge/stdio-bridge.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c index 16f4bdb809..52b9ce4555 100644 --- a/src/stdio-bridge/stdio-bridge.c +++ b/src/stdio-bridge/stdio-bridge.c @@ -240,9 +240,10 @@ static int run(int argc, char *argv[]) { { struct pollfd p[3] = { - {.fd = fd, .events = events_a, }, - {.fd = STDIN_FILENO, .events = events_b & POLLIN, }, - {.fd = STDOUT_FILENO, .events = events_b & POLLOUT, }}; + {.fd = fd, .events = events_a }, + {.fd = STDIN_FILENO, .events = events_b & POLLIN }, + {.fd = STDOUT_FILENO, .events = events_b & POLLOUT }, + }; r = ppoll(p, ELEMENTSOF(p), ts, NULL); } From dd90e39cb6f1bd078aa5bf3c37963d5adb06a1c3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Mar 2019 15:39:07 +0100 Subject: [PATCH 8/9] util: add one more disconnect errno code --- src/basic/errno-util.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h index 067b4fa303..615b6a806a 100644 --- a/src/basic/errno-util.h +++ b/src/basic/errno-util.h @@ -35,7 +35,8 @@ static inline int negative_errno(void) { #define ERRNO_IS_DISCONNECT(r) \ IN_SET(abs(r), \ ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \ - ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, ENONET) + ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, \ + ENONET, ESHUTDOWN) /* Resource exhaustion, could be our fault or general system trouble */ #define ERRNO_IS_RESOURCE(r) \ From f60a028a4e8633245592370264665ba203a56193 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Mar 2019 15:39:34 +0100 Subject: [PATCH 9/9] tree-wide: use ERRNO_IS_DISCONNECT() at more places --- src/core/manager.c | 4 ++-- src/libsystemd/sd-bus/sd-bus.c | 11 ++++++----- src/socket-proxy/socket-proxyd.c | 7 ++++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index eecf48dea5..22d1fda2dc 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -3056,7 +3056,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) { } if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { - if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED)) + if (!IN_SET(errno, EAGAIN, ENOENT) && !ERRNO_IS_DISCONNECT(errno)) log_error_errno(errno, "connect() failed: %m"); return; } @@ -3068,7 +3068,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) { errno = 0; if (write(fd, message, n + 1) != n + 1) - if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED)) + if (!IN_SET(errno, EAGAIN, ENOENT) && !ERRNO_IS_DISCONNECT(errno)) log_error_errno(errno, "Failed to write Plymouth message: %m"); } diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index f7177963c2..3df7c86b89 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -28,6 +28,7 @@ #include "bus-util.h" #include "cgroup-util.h" #include "def.h" +#include "errno-util.h" #include "fd-util.h" #include "hexdecoct.h" #include "hostname-util.h" @@ -1928,7 +1929,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) { r = bus_write_message(bus, m, &idx); if (r < 0) { - if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) { + if (ERRNO_IS_DISCONNECT(r)) { bus_enter_closing(bus); return -ECONNRESET; } @@ -2224,7 +2225,7 @@ _public_ int sd_bus_call( r = bus_read_message(bus, false, 0); if (r < 0) { - if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) { + if (ERRNO_IS_DISCONNECT(r)) { bus_enter_closing(bus); r = -ECONNRESET; } @@ -2257,7 +2258,7 @@ _public_ int sd_bus_call( r = dispatch_wqueue(bus); if (r < 0) { - if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) { + if (ERRNO_IS_DISCONNECT(r)) { bus_enter_closing(bus); r = -ECONNRESET; } @@ -3015,7 +3016,7 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit assert_not_reached("Unknown state"); } - if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) { + if (ERRNO_IS_DISCONNECT(r)) { bus_enter_closing(bus); r = 1; } else if (r < 0) @@ -3146,7 +3147,7 @@ _public_ int sd_bus_flush(sd_bus *bus) { for (;;) { r = dispatch_wqueue(bus); if (r < 0) { - if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) { + if (ERRNO_IS_DISCONNECT(r)) { bus_enter_closing(bus); return -ECONNRESET; } diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c index bac5c164d4..fc7e4958be 100644 --- a/src/socket-proxy/socket-proxyd.c +++ b/src/socket-proxy/socket-proxyd.c @@ -16,6 +16,7 @@ #include "sd-resolve.h" #include "alloc-util.h" +#include "errno-util.h" #include "fd-util.h" #include "log.h" #include "main-func.h" @@ -29,8 +30,8 @@ #include "util.h" #define BUFFER_SIZE (256 * 1024) -static unsigned arg_connections_max = 256; +static unsigned arg_connections_max = 256; static const char *arg_remote_host = NULL; typedef struct Context { @@ -141,7 +142,7 @@ static int connection_shovel( if (z > 0) { *full += z; shoveled = true; - } else if (z == 0 || IN_SET(errno, EPIPE, ECONNRESET)) { + } else if (z == 0 || ERRNO_IS_DISCONNECT(errno)) { *from_source = sd_event_source_unref(*from_source); *from = safe_close(*from); } else if (!IN_SET(errno, EAGAIN, EINTR)) @@ -153,7 +154,7 @@ static int connection_shovel( if (z > 0) { *full -= z; shoveled = true; - } else if (z == 0 || IN_SET(errno, EPIPE, ECONNRESET)) { + } else if (z == 0 || ERRNO_IS_DISCONNECT(errno)) { *to_source = sd_event_source_unref(*to_source); *to = safe_close(*to); } else if (!IN_SET(errno, EAGAIN, EINTR))