From: David Herrmann Date: Thu, 2 Oct 2014 06:31:28 +0000 (+0200) Subject: barrier: fix up constructor error handling X-Git-Tag: v217~375 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=fc808616227115ccab8c04f00f8f7472c7353ae5;hp=dda57d9143644d39091207b287f142f91f55d0ad 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. --- diff --git a/src/shared/barrier.c b/src/shared/barrier.c index 4a5544de2..f65363a67 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 53b4439fb..c55e31134 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);