git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Cc: Josh Hagins <hagins.josh@gmail.com>,
	Git Mailing List <git@vger.kernel.org>
Subject: [PATCH 1/3] usage.c: add BUG() function
Date: Fri, 12 May 2017 23:28:50 -0400	[thread overview]
Message-ID: <20170513032850.zeru4cm2l7i23rkc@sigill.intra.peff.net> (raw)
In-Reply-To: <20170513032414.mfrwabt4hovujde2@sigill.intra.peff.net>

There's a convention in Git's code base to write assertions
as:

  if (...some_bad_thing...)
	die("BUG: the terrible thing happened");

with the idea that users should never see a "BUG:" message
(but if they, it at least gives a clue what happened).  We
use die() here because it's convenient, but there are a few
draw-backs:

  1. Without parsing the messages, it's hard for callers to
     distinguish BUG assertions from regular errors.

     For instance, it would be nice if the test suite could
     check that we don't hit any assertions, but
     test_must_fail will pass BUG deaths as OK.

  2. It would be useful to add more debugging features to
     BUG assertions, like file/line numbers or dumping core.

  3. The die() handler can be replaced, and might not
     actually exit the whole program (e.g., it may just
     pthread_exit()). This is convenient for normal errors,
     but for an assertion failure (which is supposed to
     never happen), we're probably better off taking down
     the whole process as quickly and cleanly as possible.

We could address these by checking in die() whether the
error message starts with "BUG", and behaving appropriately.
But there's little advantage at that point to sharing the
die() code, and only downsides (e.g., we can't change the
BUG() interface independently). Moreover, converting all of
the existing BUG calls reveals that the test suite does
indeed trigger a few of them.

Instead, this patch introduces a new BUG() function, which
prints an error before dying via SIGABRT. This gives us test
suite checking and core dumps.  The function is actually a
macro (when supported) so that we can show the file/line
number.

We can convert die("BUG") invocations to BUG() in further
patches, dealing with any test fallouts individually.

Signed-off-by: Jeff King <peff@peff.net>
---
I actually don't care that much about the file/line thing
personally. The messages are generally unique, which lets
you find them in the code base easily. And it does introduce
a lot of complexity due to the variadic macro fallback. So
we could just drop it and have a much simpler patch
(basically just die() without the abstracted handler, and
with abort() instead of exit()).

 git-compat-util.h |  9 +++++++++
 usage.c           | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/git-compat-util.h b/git-compat-util.h
index bd04564a6..4575b3890 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -1064,6 +1064,15 @@ static inline int regexec_buf(const regex_t *preg, const char *buf, size_t size,
 #define HAVE_VARIADIC_MACROS 1
 #endif
 
+#ifdef HAVE_VARIADIC_MACROS
+__attribute__((format (printf, 3, 4))) NORETURN
+void BUG_fl(const char *file, int line, const char *fmt, ...);
+#define BUG(...) BUG_fl(__FILE__, __LINE__, __VA_ARGS__)
+#else
+__attribute__((format (printf, 1, 2))) NORETURN
+void BUG(const char *fmt, ...);
+#endif
+
 /*
  * Preserves errno, prints a message, but gives no warning for ENOENT.
  * Returns 0 on success, which includes trying to unlink an object that does
diff --git a/usage.c b/usage.c
index ad6d2910f..7e6cb2028 100644
--- a/usage.c
+++ b/usage.c
@@ -201,3 +201,35 @@ void warning(const char *warn, ...)
 	warn_routine(warn, params);
 	va_end(params);
 }
+
+static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params)
+{
+	char prefix[256];
+
+	/* truncation via snprintf is OK here */
+	if (file)
+		snprintf(prefix, sizeof(prefix), "BUG: %s:%d: ", file, line);
+	else
+		snprintf(prefix, sizeof(prefix), "BUG: ");
+
+	vreportf(prefix, fmt, params);
+	abort();
+}
+
+#ifdef HAVE_VARIADIC_MACROS
+void BUG_fl(const char *file, int line, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	BUG_vfl(file, line, fmt, ap);
+	va_end(ap);
+}
+#else
+void BUG(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	BUG_vfl(NULL, 0, fmt, ap);
+	va_end(ap);
+}
+#endif
-- 
2.13.0.452.g0afc8e12b


  reply	other threads:[~2017-05-13  3:28 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-12 14:19 [Git 2.13.0] BUG: setup_git_env called without repository Josh Hagins
2017-05-12 14:48 ` Johannes Schindelin
2017-05-15  0:22   ` Josh Hagins
2017-05-12 20:34 ` [PATCH] config: complain about --local outside of a git repo Jeff King
2017-05-12 22:31   ` Ævar Arnfjörð Bjarmason
2017-05-13  2:03     ` Jeff King
2017-05-13  3:24       ` [PATCH 0/3] BUG() and "config --local" outside of repo Jeff King
2017-05-13  3:28         ` Jeff King [this message]
2017-05-13  3:55           ` [PATCH 1/3] usage.c: add BUG() function Jeff King
2017-05-15  2:28             ` Junio C Hamano
2017-05-13  3:29         ` [PATCH 2/3] setup_git_env: convert die("BUG") to BUG() Jeff King
2017-05-13  3:29         ` [PATCH 3/3] config: complain about --local outside of a git repo Jeff King
2018-05-02  9:38         ` [PATCH v2 0/4] Finish the conversion from die("BUG: ...") to BUG() Johannes Schindelin
2018-05-02  9:38           ` [PATCH v2 1/4] test-tool: help verifying BUG() code paths Johannes Schindelin
2018-05-02 15:18             ` Duy Nguyen
2018-05-05 19:30               ` Johannes Schindelin
2018-05-02  9:38           ` [PATCH v2 2/4] run-command: use BUG() to report bugs, not die() Johannes Schindelin
2018-05-07  9:08             ` Jeff King
2018-05-02  9:38           ` [PATCH v2 3/4] Replace all die("BUG: ...") calls by BUG() ones Johannes Schindelin
2018-05-02  9:38           ` [PATCH v2 4/4] Convert remaining die*(BUG) messages Johannes Schindelin
2018-05-07  9:01           ` [PATCH v2 0/4] Finish the conversion from die("BUG: ...") to BUG() Jeff King
2017-05-13  0:04   ` [PATCH] config: complain about --local outside of a git repo Jonathan Nieder
2017-05-13  2:04     ` Jeff King
2017-05-15  0:31   ` Josh Hagins
2017-05-15  3:18     ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170513032850.zeru4cm2l7i23rkc@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=hagins.josh@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).