diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-10-02 08:31:28 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-10-02 08:40:43 +0200 |
commit | fc808616227115ccab8c04f00f8f7472c7353ae5 (patch) | |
tree | 5a3602427608b7fb975dacdc19579a28261d0ec1 | |
parent | dda57d9143644d39091207b287f142f91f55d0ad (diff) |
barrier: fix up constructor error handling
We cannot rely on "errno" to be non-zero on failure, if we perform
multiple glibc calls. That is, if the first eventfd() call fails, but the
second succeeds, we cleanup the barrier but return 0.
Fix this by always testing the return value immediately. This should also
fix all the coverity warnings.
-rw-r--r-- | src/shared/barrier.c | 19 | ||||
-rw-r--r-- | src/shared/barrier.h | 2 |
2 files changed, 16 insertions, 5 deletions
diff --git a/src/shared/barrier.c b/src/shared/barrier.c index 4a5544de27..f65363a67b 100644 --- a/src/shared/barrier.c +++ b/src/shared/barrier.c @@ -112,15 +112,24 @@ * Returns: 0 on success, negative error code on failure. */ int barrier_create(Barrier *b) { + _cleanup_(barrier_destroyp) Barrier *staging = b; + int r; + assert(b); - if ((b->me = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) < 0 || - (b->them = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) < 0 || - pipe2(b->pipe, O_CLOEXEC | O_NONBLOCK) < 0) { - barrier_destroy(b); + b->me = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if (b->me < 0) + return -errno; + + b->them = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if (b->them < 0) + return -errno; + + r = pipe2(b->pipe, O_CLOEXEC | O_NONBLOCK); + if (r < 0) return -errno; - } + staging = NULL; return 0; } diff --git a/src/shared/barrier.h b/src/shared/barrier.h index 53b4439fb2..c55e311344 100644 --- a/src/shared/barrier.h +++ b/src/shared/barrier.h @@ -62,6 +62,8 @@ struct Barrier { int barrier_create(Barrier *obj); void barrier_destroy(Barrier *b); +DEFINE_TRIVIAL_CLEANUP_FUNC(Barrier*, barrier_destroy); + void barrier_set_role(Barrier *b, unsigned int role); bool barrier_place(Barrier *b); |