From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-2.9 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=unavailable version=3.3.2 X-Original-To: cmogstored-public@bogomips.org Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id ABA681F5AF for ; Mon, 9 Mar 2015 20:48:57 +0000 (UTC) From: Eric Wong To: cmogstored-public@bogomips.org Subject: [PATCH 1/2] Fix assertion failure during startup Date: Mon, 9 Mar 2015 20:49:00 +0000 Message-Id: <1425934141-28750-1-git-send-email-e@80x24.org> In-Reply-To: <20150309203543.GA18791@dcvr.yhbt.net> References: <20150309203543.GA18791@dcvr.yhbt.net> List-Id: During the initial device scan, it is possible for the waiter to be interrupted while awaiting cancellation. We must account for this on all platforms regardless of whether pselect or ppoll is used. Reported-by: Mykola Golub ref: <20150309151851.GC2195@gmail.com> --- cmogstored.h | 2 +- mnt.c | 6 +++++- sig.c | 26 ++++++++++++++++++-------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/cmogstored.h b/cmogstored.h index c6c5291..a7309b5 100644 --- a/cmogstored.h +++ b/cmogstored.h @@ -291,7 +291,7 @@ struct mog_file { extern sigset_t mog_emptyset; void mog_intr_disable(void); void mog_intr_enable(void); -void mog_sleep(long seconds); +int mog_sleep(long seconds); #include "selfwake.h" enum mog_fd_type { diff --git a/mnt.c b/mnt.c index 0de0bb9..ca4bdf8 100644 --- a/mnt.c +++ b/mnt.c @@ -122,6 +122,7 @@ skip: static void * init_once(void *ptr) { struct init_args *ia = ptr; + int err; CHECK(int, 0, pthread_mutex_lock(&by_dev_lock) ); assert(by_dev == NULL && @@ -135,7 +136,10 @@ static void * init_once(void *ptr) CHECK(int, 0, pthread_cond_signal(&ia->cond)); CHECK(int, 0, pthread_mutex_unlock(&ia->cond_lock)); - mog_sleep(-1); /* wait for cancellation */ + /* wait for cancellation, mog_sleep may return ENOMEM or EINTR */ + do { + err = mog_sleep(-1); + } while (err == EINTR || err == ENOMEM); assert(0 && "init_once did not get cancelled"); return NULL; } diff --git a/sig.c b/sig.c index c04117a..cfbffc2 100644 --- a/sig.c +++ b/sig.c @@ -32,23 +32,33 @@ void mog_intr_enable(void) * would increase the size of the executable */ #ifdef HAVE_PPOLL -static void sleeper(struct timespec *tsp, const sigset_t *sigmask) +static int sleeper(struct timespec *tsp, const sigset_t *sigmask) { - if (ppoll(NULL, 0, tsp, sigmask) < 0) - assert((errno == EINTR || errno == ENOMEM) && + int err = 0; + + if (ppoll(NULL, 0, tsp, sigmask) < 0) { + err = errno; + assert((err == EINTR || err == ENOMEM) && "BUG in ppoll usage"); + } + return err; } #else /* PSELECT */ -static void sleeper(struct timespec *tsp, const sigset_t *sigmask) +static int sleeper(struct timespec *tsp, const sigset_t *sigmask) { - if (pselect(0, NULL, NULL, NULL, tsp, sigmask) < 0) - assert((errno == EINTR || errno == ENOMEM) && + int err = 0; + + if (pselect(0, NULL, NULL, NULL, tsp, sigmask) < 0) { + err = errno; + assert((err == EINTR || err == ENOMEM) && "BUG in pselect usage"); + } + return err; } #endif /* PSELECT */ /* thread-safe, interruptible sleep, negative seconds -> sleep forever */ -void mog_sleep(long seconds) +int mog_sleep(long seconds) { struct timespec ts; struct timespec *tsp; @@ -61,5 +71,5 @@ void mog_sleep(long seconds) tsp = &ts; } - sleeper(tsp, &mog_emptyset); + return sleeper(tsp, &mog_emptyset); } -- EW