]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Introduce RET_GATHER and use it in src/shared/
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 9 Jul 2023 19:25:42 +0000 (13:25 -0600)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 13 Jul 2023 09:12:00 +0000 (11:12 +0200)
The idea is to make it easier to implement the common pattern of
accumulating errors (negative values) in an accumulator to return
the first error.

src/basic/errno-util.h
src/shared/bus-util.c
src/shared/devnode-acl.c
src/shared/nscd-flush.c
src/test/test-errno-util.c

index 091f99c5902ad644f3264513384e05a4d310f8ef..f477db78525307d5237080c38d4be7b81309e30e 100644 (file)
@@ -73,6 +73,16 @@ static inline int RET_NERRNO(int ret) {
         return ret;
 }
 
+/* Collect possible errors in <acc>, so that the first error can be returned.
+ * Returns (possibly updated) <acc>. */
+#define RET_GATHER(acc, err)                    \
+        ({                                      \
+                int *__a = &(acc), __e = (err); \
+                if (*__a >= 0 && __e < 0)       \
+                        *__a = __e;             \
+                *__a;                           \
+        })
+
 static inline int errno_or_else(int fallback) {
         /* To be used when invoking library calls where errno handling is not defined clearly: we return
          * errno if it is set, and the specified error otherwise. The idea is that the caller initializes
index d4c91fa3aab36ca538dee85d31192d53bea17a97..4123152d93a91944af83d6cb51f383cdbfe002ea 100644 (file)
@@ -516,14 +516,8 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
 
         /* Continues adding after failure, and returns the first failure. */
 
-        STRV_FOREACH(i, l) {
-                int k;
-
-                k = sd_bus_track_add_name(t, *i);
-                if (k < 0 && r >= 0)
-                        r = k;
-        }
-
+        STRV_FOREACH(i, l)
+                RET_GATHER(r, sd_bus_track_add_name(t, *i));
         return r;
 }
 
index 92a2aff3dc29f3527da5399982cb8b095b830d91..b239699e8ace40b8422be8184c2f254b6a179dd0 100644 (file)
@@ -218,8 +218,8 @@ int devnode_acl_all(const char *seat,
                 k = devnode_acl(n, flush, del, old_uid, add, new_uid);
                 if (k == -ENOENT)
                         log_debug("Device %s disappeared while setting ACLs", n);
-                else if (k < 0 && r == 0)
-                        r = k;
+                else
+                        RET_GATHER(r, k);
         }
 
         return r;
index dfc7db6964dc6e849c4d90ec4f41c40c1cf973e2..6df18d7aac7ba2eb5441b40e8443ee1cfcf625fe 100644 (file)
@@ -128,21 +128,15 @@ static int nscd_flush_cache_one(const char *database, usec_t end) {
 }
 
 int nscd_flush_cache(char **databases) {
-        usec_t end;
         int r = 0;
 
-        /* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s timeout, so that we
-         * don't block indefinitely on another service. */
+        /* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s timeout,
+         * so that we don't block indefinitely on another service. */
 
-        end = usec_add(now(CLOCK_MONOTONIC), NSCD_FLUSH_CACHE_TIMEOUT_USEC);
+        usec_t end = usec_add(now(CLOCK_MONOTONIC), NSCD_FLUSH_CACHE_TIMEOUT_USEC);
 
-        STRV_FOREACH(i, databases) {
-                int k;
-
-                k = nscd_flush_cache_one(*i, end);
-                if (k < 0 && r >= 0)
-                        r = k;
-        }
+        STRV_FOREACH(i, databases)
+                RET_GATHER(r, nscd_flush_cache_one(*i, end));
 
         return r;
 }
index d3d022c33fff7bb57d13f2bc9963582f8a62f7f3..62a508c4c9d33371df37de251fb8437355211bf2 100644 (file)
@@ -78,4 +78,15 @@ TEST(UNPROTECT_ERRNO) {
         assert_se(errno == 4711);
 }
 
+TEST(RET_GATHER) {
+        int x = 0, y = 2;
+
+        assert_se(RET_GATHER(x, 5) == 0);
+        assert_se(RET_GATHER(x, -5) == -5);
+        assert_se(RET_GATHER(x, -1) == -5);
+
+        assert_se(RET_GATHER(x, y++) == -5);
+        assert_se(y == 3);
+}
+
 DEFINE_TEST_MAIN(LOG_INFO);