git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
	"Jeff Hostetler" <jeffhost@microsoft.com>,
	"Taylor Blau" <me@ttaylorr.com>, "Jeff King" <peff@peff.net>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: [PATCH v1] common-main.c: call exit(), don't return
Date: Mon,  6 Dec 2021 17:11:03 +0100	[thread overview]
Message-ID: <patch-v1-1.1-6fedf9969b6-20211206T161001Z-avarab@gmail.com> (raw)

Change the main() function to call "exit()" instead of ending with a
"return" statement. The "exit()" function is our own wrapper that
calls trace2_cmd_exit_fl() for us, from git-compat-util.h:

	#define exit(code) exit(trace2_cmd_exit_fl(__FILE__, __LINE__, (code)))

That "exit()" wrapper has been in use ever since ee4512ed481 (trace2:
create new combined trace facility, 2019-02-22).

This changes nothing about how we "exit()", as we'd invoke
"trace2_cmd_exit_fl()" in both cases due to the wrapper, this change
makes it easier to reason about this code, as we're now always
obviously relying on our "exit()" wrapper.

There is already code immediately downstream of our "main()" which has
a hard reliance on that, e.g. the various "exit()" calls downstream of
"cmd_main()" in "git.c".

We even had a comment in "t/helper/test-trace2.c" that seemed to be
confused about how the "exit()" wrapper interacted with uses of
"return", even though it was introduced in the same trace2 series in
a15860dca3f (trace2: t/helper/test-trace2, t0210.sh, t0211.sh,
t0212.sh, 2019-02-22), after the aforementioned ee4512ed481. Perhaps
it pre-dated the "exit()" wrapper?

Let's also update both the documentation and comments accordingly: The
documentation added in e544221d97a (trace2:
Documentation/technical/api-trace2.txt, 2019-02-22) already said of
the "exit" event that "[it] is emitted when git calls `exit()". But
the "main()" example then called trace2_cmd_exit(). Let's have it
invoke "exit()" instead, as the code in "common-main.c" now does.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---

The diffstat here is neutral, and as noted this changes no behavior,
so this isn't really needed for anything.

But as argued above I think this makes things a lot easier for readers
of the code. I've had at least a couple of traces through git's
execution from command-main.c downwards and thought that the "exit()"
calls in git.c might be a bug, until I (re-)discovered that we're
defining an exit() wrapper via a macro.

It might be a good follow-up at some point to see if we could hoist
some of the cleanups we do in run_builtin() to to this level. I.e. the
code referenced in my 338abb0f045 (builtins + test helpers: use return
instead of exit() in cmd_*, 2021-06-08) (and similar).

Even that code could probably do with some tweaks, e.g. we should
probably try to fflush() stdout/stderr even if we're about to return
non-zero (now we'll only do it on success).

But for now this is one small readability improvement to some code
central to git's execution.

A version of this was originally submitted as
https://lore.kernel.org/git/RFC-patch-07.21-3f897bf6b0e-20211115T220831Z-avarab@gmail.com/;
range-diff against that initial version below.

Range-diff against v0:
1:  3f897bf6b0e ! 1:  6fedf9969b6 common-main.c: call exit(), don't return
    @@ Metadata
      ## Commit message ##
         common-main.c: call exit(), don't return
     
    -    Refactor the main() function so that we always take the same path
    -    towards trace2_cmd_exit() whether exit() is invoked, or we end up in
    -    the "return" in the pre-image. This contains no functional change, and
    -    is only intended for the benefit of readers of the code, who'll now be
    -    pointed to our exit() wrapper.
    -
    -    Since ee4512ed481 (trace2: create new combined trace facility,
    -    2019-02-22) we've defined "exit" with a macro to call
    -    trace2_cmd_exit() for us in "git-compat-util.h". So in cases where an
    -    exit() is invoked (such as in several places in "git.c") we don't
    -    reach the trace2_cmd_exit() in the pre-image. This makes it so that
    -    we'll always take that same exit() path.
    +    Change the main() function to call "exit()" instead of ending with a
    +    "return" statement. The "exit()" function is our own wrapper that
    +    calls trace2_cmd_exit_fl() for us, from git-compat-util.h:
    +
    +            #define exit(code) exit(trace2_cmd_exit_fl(__FILE__, __LINE__, (code)))
    +
    +    That "exit()" wrapper has been in use ever since ee4512ed481 (trace2:
    +    create new combined trace facility, 2019-02-22).
    +
    +    This changes nothing about how we "exit()", as we'd invoke
    +    "trace2_cmd_exit_fl()" in both cases due to the wrapper, this change
    +    makes it easier to reason about this code, as we're now always
    +    obviously relying on our "exit()" wrapper.
    +
    +    There is already code immediately downstream of our "main()" which has
    +    a hard reliance on that, e.g. the various "exit()" calls downstream of
    +    "cmd_main()" in "git.c".
    +
    +    We even had a comment in "t/helper/test-trace2.c" that seemed to be
    +    confused about how the "exit()" wrapper interacted with uses of
    +    "return", even though it was introduced in the same trace2 series in
    +    a15860dca3f (trace2: t/helper/test-trace2, t0210.sh, t0211.sh,
    +    t0212.sh, 2019-02-22), after the aforementioned ee4512ed481. Perhaps
    +    it pre-dated the "exit()" wrapper?
    +
    +    Let's also update both the documentation and comments accordingly: The
    +    documentation added in e544221d97a (trace2:
    +    Documentation/technical/api-trace2.txt, 2019-02-22) already said of
    +    the "exit" event that "[it] is emitted when git calls `exit()". But
    +    the "main()" example then called trace2_cmd_exit(). Let's have it
    +    invoke "exit()" instead, as the code in "common-main.c" now does.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    + ## Documentation/technical/api-trace2.txt ##
    +@@ Documentation/technical/api-trace2.txt: Initialization::
    + ----------------
    + int main(int argc, const char **argv)
    + {
    +-	int exit_code;
    +-
    + 	trace2_initialize();
    + 	trace2_cmd_start(argv);
    + 
    +-	exit_code = cmd_main(argc, argv);
    +-
    +-	trace2_cmd_exit(exit_code);
    +-
    +-	return exit_code;
    ++	/* Our exit() will call trace2_cmd_exit_fl() */
    ++	exit(cmd_main(argc, argv));
    + }
    + ----------------
    + 
    +
      ## common-main.c ##
     @@ common-main.c: int main(int argc, const char **argv)
      
    @@ common-main.c: int main(int argc, const char **argv)
     +	 */
     +	exit(result);
      }
    +
    + ## t/helper/test-trace2.c ##
    +@@ t/helper/test-trace2.c: static int print_usage(void)
    +  *    [] the "cmd_name" event has been generated.
    +  *    [] this writes various "def_param" events for interesting config values.
    +  *
    +- * We further assume that if we return (rather than exit()), trace2_cmd_exit()
    +- * will be called by test-tool.c:cmd_main().
    ++ * It doesn't matter if we "return" here or call "exit()", since our
    ++ * "exit()" is a wrapper that will call trace2_cmd_exit_fl. It would
    ++ * matter if we bypassed it and called "_exit()". Even if it doesn't
    ++ * matter for the narrow case of trace2 testing, let's be nice to
    ++ * test-tool.c's "cmd_main()" and common-main.c's "main()" and
    ++ * "return" here.
    +  */
    + int cmd__trace2(int argc, const char **argv)
    + {
    +
    + ## trace2.h ##
    +@@ trace2.h: void trace2_cmd_start_fl(const char *file, int line, const char **argv);
    +  */
    + int trace2_cmd_exit_fl(const char *file, int line, int code);
    + 
    +-#define trace2_cmd_exit(code) (trace2_cmd_exit_fl(__FILE__, __LINE__, (code)))
    +-
    + /*
    +  * Emit an 'error' event.
    +  *

 Documentation/technical/api-trace2.txt | 9 ++-------
 common-main.c                          | 9 ++++++---
 t/helper/test-trace2.c                 | 8 ++++++--
 trace2.h                               | 2 --
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/Documentation/technical/api-trace2.txt b/Documentation/technical/api-trace2.txt
index bb13ca3db8b..568a909222a 100644
--- a/Documentation/technical/api-trace2.txt
+++ b/Documentation/technical/api-trace2.txt
@@ -828,16 +828,11 @@ Initialization::
 ----------------
 int main(int argc, const char **argv)
 {
-	int exit_code;
-
 	trace2_initialize();
 	trace2_cmd_start(argv);
 
-	exit_code = cmd_main(argc, argv);
-
-	trace2_cmd_exit(exit_code);
-
-	return exit_code;
+	/* Our exit() will call trace2_cmd_exit_fl() */
+	exit(cmd_main(argc, argv));
 }
 ----------------
 
diff --git a/common-main.c b/common-main.c
index 71e21dd20a3..eafc70718a5 100644
--- a/common-main.c
+++ b/common-main.c
@@ -51,7 +51,10 @@ int main(int argc, const char **argv)
 
 	result = cmd_main(argc, argv);
 
-	trace2_cmd_exit(result);
-
-	return result;
+	/*
+	 * We define exit() to call trace2_cmd_exit_fl() in
+	 * git-compat-util.h. Whether we reach this or exit()
+	 * elsewhere we'll always run our trace2 exit handler.
+	 */
+	exit(result);
 }
diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c
index f93633f895a..9954010bc89 100644
--- a/t/helper/test-trace2.c
+++ b/t/helper/test-trace2.c
@@ -262,8 +262,12 @@ static int print_usage(void)
  *    [] the "cmd_name" event has been generated.
  *    [] this writes various "def_param" events for interesting config values.
  *
- * We further assume that if we return (rather than exit()), trace2_cmd_exit()
- * will be called by test-tool.c:cmd_main().
+ * It doesn't matter if we "return" here or call "exit()", since our
+ * "exit()" is a wrapper that will call trace2_cmd_exit_fl. It would
+ * matter if we bypassed it and called "_exit()". Even if it doesn't
+ * matter for the narrow case of trace2 testing, let's be nice to
+ * test-tool.c's "cmd_main()" and common-main.c's "main()" and
+ * "return" here.
  */
 int cmd__trace2(int argc, const char **argv)
 {
diff --git a/trace2.h b/trace2.h
index 0cc7b5f5312..73876781294 100644
--- a/trace2.h
+++ b/trace2.h
@@ -110,8 +110,6 @@ void trace2_cmd_start_fl(const char *file, int line, const char **argv);
  */
 int trace2_cmd_exit_fl(const char *file, int line, int code);
 
-#define trace2_cmd_exit(code) (trace2_cmd_exit_fl(__FILE__, __LINE__, (code)))
-
 /*
  * Emit an 'error' event.
  *
-- 
2.34.1.898.g5a552c2e5f0


             reply	other threads:[~2021-12-06 16:15 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-06 16:11 Ævar Arnfjörð Bjarmason [this message]
2021-12-06 18:43 ` [PATCH v1] common-main.c: call exit(), don't return Junio C Hamano
2021-12-07 10:13 ` [PATCH v2] " Ævar Arnfjörð Bjarmason

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

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

  git send-email \
    --in-reply-to=patch-v1-1.1-6fedf9969b6-20211206T161001Z-avarab@gmail.com \
    --to=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jeffhost@microsoft.com \
    --cc=me@ttaylorr.com \
    --cc=peff@peff.net \
    /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.
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 NNTP newsgroup(s).