1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-18 10:04:04 +03:00

Introduce RET_GATHER and use it in src/shared/

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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2023-07-09 13:25:42 -06:00
parent c8e02e408f
commit 809c3a84e1
5 changed files with 30 additions and 21 deletions

View 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

View 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;
}

View 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;

View 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;
}

View 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);