git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: thoughts on error passing, was Re: [PATCH 2/2] fsck: handle bad trees like other errors

From
Jeff King <peff@peff.net>
Date
Sep 28, 2016, 08:58 UTC
Message-ID
<20160928085841.aoisson3fnuke47q@sigill.intra.peff.net>
In-Reply-To
<06b1a3bc-18dc-bd9e-4200-a2eedbec7b97@alum.mit.edu>
On Wed, Sep 28, 2016 at 07:01:38AM +0200, Michael Haggerty wrote:
Show 8 quoted lines
> >   - a global for chaining to error, like:
> > 
> >        struct error_context print_errors = {
> >           error, /* actually a wrapper to handle va_list and NULL data */
> >           NULL
> >        };
> 
> There could also be a global for chaining to `warn()` or `die()`.

I played around a little with this. The latter actually makes a lot of code cleaner, because we can rely on the functions not returning at all. So for example, you get:

diff --git a/branch.c b/branch.c
index a5a8dcb..53404b8 100644
--- a/branch.c
+++ b/branch.c
@@ -303,17 +303,13 @@ void create_branch(const char *head,
 
 	if (!dont_change_ref) {
 		struct ref_transaction *transaction;
-		struct strbuf err = STRBUF_INIT;
-
-		transaction = ref_transaction_begin(&err);
-		if (!transaction ||
-		    ref_transaction_update(transaction, ref.buf,
-					   sha1, forcing ? NULL : null_sha1,
-					   0, msg, &err) ||
-		    ref_transaction_commit(transaction, &err))
-			die("%s", err.buf);
+
+		transaction = ref_transaction_begin(&error_die);
+		ref_transaction_update(transaction, ref.buf,
+				       sha1, forcing ? NULL : null_sha1,
+				       0, msg, &error_die);
+		ref_transaction_commit(transaction, &error_die);
 		ref_transaction_free(transaction);
-		strbuf_release(&err);
 	}
 
 	if (real_ref && track)

which is much shorter and to the point (it does rely on the called
functions always calling report_error() and never just returning NULL or
"-1", but that should be the already. If it isn't, we'd be printing
"fatal: " with no message).

Cases that call:

  error("%s", err.buf);

can drop the strbuf handling, but of course still need to retain their
conditionals. So they're better, but not as much. I did a half-hearted
conversion of some of the ref code that uses strbufs, and it seems like
it would save a few hundred lines of boilerplate.

There are some cases that are _worse_, because they want to prefix the
error. E.g., in init-db, we have:

  struct strbuf err = STRBUF_INIT;
  ...
  if (refs_init_db(&err))
	die("failed to set up refs db: %s", err.buf);

which is fairly clean. Using an error_context adds slightly to the
boilerplate:

  struct strbuf err_buf = STRBUF_INIT;
  struct error_context err = STRBUF_ERR(&err_buf);
  ...
  if (refs_init_db(&err))
	die("failed to set up refs db: %s", err_buf.buf);

Though if we wanted to get really magical, the err_buf/err pattern could
be its own single-line macro.

You could solve this more generally with something like:

  struct error_prefix_data err;

  error_prefix(&err, &error_die, "failed to set up refs db");
  refs_init_db(&err.err);

where error_prefix() basically sets us up to call back a function which
concatenates the prefix to the real error, then chains to error_die.
But to cover all cases, error_prefix() would actually have to format the
prefix string. Because some callers would be more like:

  error_prefix(&err, &error_print, "unable to frob %s", foo);
  do_frob(foo, &err);

We can't just save the va_list passed to error_prefix(), because it's
not valid after we return. So you have to format the prefix into a
buffer, even though in most cases we won't see an error at all (and
doing it completely correctly would involve using a strbuf, which means
there needs to be a cleanup step; yuck).

-Peff
Previous: Michael HaggertyNext: Junio C Hamano
Message 16 of 22 in “tree-walk improvements”
  1. 0/2 tree-walk improvementsDavid Turner, Sep 26, 2016
  2. 1/2 tree-walk: be more specific about corrupt tree errorsDavid Turner, Sep 26, 2016
  3. Jeff KingSep 27, 2016
  4. Junio C HamanoSep 27, 2016
  5. David TurnerSep 27, 2016
  6. 2/2 fsck: handle bad trees like other errorsDavid Turner, Sep 26, 2016
  7. Junio C HamanoSep 26, 2016
  8. Junio C HamanoSep 26, 2016
  9. Junio C HamanoSep 26, 2016
  10. Jeff KingSep 27, 2016
  11. David TurnerSep 27, 2016
  12. thoughts on error passing, was Re: [PATCH 2/2] fsck: handle bad trees like other errorsJeff King, Sep 27, 2016
  13. David TurnerSep 27, 2016
  14. Jeff KingSep 28, 2016
  15. Michael HaggertySep 28, 2016
  16. Jeff KingSep 28, 2016
  17. Junio C HamanoSep 28, 2016
  18. Stefan BellerSep 26, 2016
  19. Junio C HamanoSep 26, 2016
  20. David TurnerSep 26, 2016
  21. Junio C HamanoSep 27, 2016
  22. Junio C HamanoSep 26, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.