threads / bug / 60903

Bug report: Incorrect GIT_FLUSH behavior in 2.43.1 (regression and breaking)

Subject: Bug report: Incorrect GIT_FLUSH behavior in 2.43.1 (regression and breaking)

## tl;dr

7 messages between Feb 12, 2024 and Feb 14, 2024.

replies: 6people: 3as markdown or json

Xiaoguang WANG· Feb 12, 2024, 15:18 UTC · lore
Ref: https://github.com/git/git/commit/556e68032f8248c831e48207e5cb923c9fe0e42c

If GIT_FLUSH=true, it should mean to "do the flush". But that commit made skip_stdout_flush=true when GIT_FLUSH=true.

And by the way, only accepting GIT_FLUSH=true is quite breaking, it drops the compatibility of GIT_FLUSH=1: it causes the existing programs which depend on the "flushing(GIT_FLUSH=1)" behavior would hang forever if they use the new git binary, because the program won't see any flushed output ....

Junio C Hamano· Feb 12, 2024, 17:11 UTC · re: Xiaoguang WANG · lore

Re: Bug report: Incorrect GIT_FLUSH behavior in 2.43.1 (regression and breaking)

Xiaoguang WANG <wxiaoguang@gmail.com> writes:
> If GIT_FLUSH=true, it should mean to "do the flush". But that commit
> made skip_stdout_flush=true when GIT_FLUSH=true.

Thanks for reporting. I am surprised that this flipping of polarity slipped through.

> And by the way, only accepting GIT_FLUSH=true is quite breaking, it
> drops the compatibility of GIT_FLUSH=1

I do not think so. If the polarity is corrected, git_env_bool() would say "that's affirmative" when any one of the "1", "true", "yes", "on", etc. is given. If you have been passing "1", you should get the "always flush" behaviour.

Perhaps something like this would fix it?
 write-or-die.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git c/write-or-die.c w/write-or-die.c
index 3942152865..3ecb9e2af5 100644
--- c/write-or-die.c
+++ w/write-or-die.c
@@ -22,8 +22,11 @@ void maybe_flush_or_die(FILE *f, const char *desc)
 
 	if (f == stdout) {
 		if (skip_stdout_flush < 0) {
-			skip_stdout_flush = git_env_bool("GIT_FLUSH", -1);
-			if (skip_stdout_flush < 0) {
+			int flush_setting = git_env_bool("GIT_FLUSH", -1);
+
+			if (0 <= flush_setting)
+				skip_stdout_flush = !flush_setting;
+			else {
 				struct stat st;
 				if (fstat(fileno(stdout), &st))
 					skip_stdout_flush = 0;
Xiaoguang WANG· Feb 12, 2024, 17:18 UTC · re: Junio C Hamano · lore

Re: Bug report: Incorrect GIT_FLUSH behavior in 2.43.1 (regression and breaking)

On Tue, Feb 13, 2024 at 1:11 AM Junio C Hamano <gitster@pobox.com> wrote:
Show 7 quoted lines
> > And by the way, only accepting GIT_FLUSH=true is quite breaking, it
> > drops the compatibility of GIT_FLUSH=1
>
> I do not think so. If the polarity is corrected, git_env_bool()
> would say "that's affirmative" when any one of the "1", "true",
> "yes", "on", etc. is given.  If you have been passing "1", you
> should get the "always flush" behaviour.

Oh yes, you are right. There is a git_parse_int call in git_parse_maybe_bool, so if the "flipping" could be fixed, then everything should be fine.

Phillip Wood· Feb 13, 2024, 11:07 UTC · re: Junio C Hamano · lore

Re: Bug report: Incorrect GIT_FLUSH behavior in 2.43.1 (regression and breaking)

On 12/02/2024 17:11, Junio C Hamano wrote:
Show 41 quoted lines
> Xiaoguang WANG <wxiaoguang@gmail.com> writes:
> 
>> If GIT_FLUSH=true, it should mean to "do the flush". But that commit
>> made skip_stdout_flush=true when GIT_FLUSH=true.
> 
> Thanks for reporting.  I am surprised that this flipping of polarity
> slipped through.
> 
>> And by the way, only accepting GIT_FLUSH=true is quite breaking, it
>> drops the compatibility of GIT_FLUSH=1
> 
> I do not think so. If the polarity is corrected, git_env_bool()
> would say "that's affirmative" when any one of the "1", "true",
> "yes", "on", etc. is given.  If you have been passing "1", you
> should get the "always flush" behaviour.
> 
> 
> Perhaps something like this would fix it?
> 
> 
>   write-or-die.c | 7 +++++--
>   1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git c/write-or-die.c w/write-or-die.c
> index 3942152865..3ecb9e2af5 100644
> --- c/write-or-die.c
> +++ w/write-or-die.c
> @@ -22,8 +22,11 @@ void maybe_flush_or_die(FILE *f, const char *desc)
>   
>   	if (f == stdout) {
>   		if (skip_stdout_flush < 0) {
> -			skip_stdout_flush = git_env_bool("GIT_FLUSH", -1);
> -			if (skip_stdout_flush < 0) {
> +			int flush_setting = git_env_bool("GIT_FLUSH", -1);
> +
> +			if (0 <= flush_setting)
> +				skip_stdout_flush = !flush_setting;
> +			else {
>   				struct stat st;
>   				if (fstat(fileno(stdout), &st))
>   					skip_stdout_flush = 0;

Given we're in a rc-period a minimal fix like this looks appropriate (though it is missing some braces according to our coding guidelines). The interaction of "skip_stdout_flush" and git_env_bool() is unfortunate, It might be clearer if we changed to having "force_stdout_flush" instead but that would be a more invasive change.

Best Wishes
Phillip
diff --git a/write-or-die.c b/write-or-die.c
index 39421528653..e68265a94a6 100644
--- a/write-or-die.c
+++ b/write-or-die.c
@@ -18,20 +18,20 @@
   */
  void maybe_flush_or_die(FILE *f, const char *desc)
  {
-        static int skip_stdout_flush = -1;
+        static int force_stdout_flush = -1;
  
          if (f == stdout) {
-                if (skip_stdout_flush < 0) {
-                        skip_stdout_flush = git_env_bool("GIT_FLUSH", -1);
-                        if (skip_stdout_flush < 0) {
+                if (force_stdout_flush < 0) {
+                        force_stdout_flush = git_env_bool("GIT_FLUSH", -1);
+                        if (force_stdout_flush < 0) {
                                  struct stat st;
                                  if (fstat(fileno(stdout), &st))
-                                        skip_stdout_flush = 0;
+                                        force_stdout_flush = 1;
                                  else
-                                        skip_stdout_flush = S_ISREG(st.st_mode);
+                                        force_stdout_flush = !S_ISREG(st.st_mode);
                          }
                  }
-                if (skip_stdout_flush && !ferror(f))
+                if (!force_stdout_flush && !ferror(f))
                          return;
          }
          if (fflush(f)) {

  
Junio C Hamano· Feb 13, 2024, 17:26 UTC · re: Phillip Wood · lore

Re: Bug report: Incorrect GIT_FLUSH behavior in 2.43.1 (regression and breaking)

Phillip Wood <phillip.wood123@gmail.com> writes:
Show 5 quoted lines
> Given we're in a rc-period a minimal fix like this looks appropriate
> (though it is missing some braces according to our coding
> guidelines). The interaction of "skip_stdout_flush" and git_env_bool()
> is unfortunate, It might be clearer if we changed to having
> "force_stdout_flush" instead but that would be a more invasive change.

I admit that I did find the polarity of the existing variable annoying, and it does make sense to flip it like you did here.

Unfortunately the minimum fix is already in 'next', so let me turn what you wrote into an update relative to that. I'll assume your patch in the discussion is signed-off already?

------- >8 ------------- >8 ------------- >8 -------
From: Phillip Wood <phillip.wood123@gmail.com>
Subject: maybe_flush_or_die(): flip the polarity of an internal variable

We take GIT_FLUSH that tells us if we want to flush (or not) from the outside, but internally use a variable that tells us to skip (or not) the flushing operation, which makes the code flow unnecessarily confusing to read.

With the understanding of the original motivation behind "skip" in 06f59e9f (Don't fflush(stdout) when it's not helpful, 2007-06-29), we can sympathize with the current naming (we wanted to avoid useless flushing of stdout by default, with an escape hatch to always flush), but it is still not a good excuse.

Retire the "skip_stdout_flush" variable and replace it with "flush_stdout" that tells if we do or do not want to run fflush().

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 write-or-die.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)
diff --git c/write-or-die.c w/write-or-die.c
index 3ecb9e2af5..01a9a51fa2 100644
--- c/write-or-die.c
+++ w/write-or-die.c
@@ -18,23 +18,20 @@
  */
 void maybe_flush_or_die(FILE *f, const char *desc)
 {
-	static int skip_stdout_flush = -1;
-
 	if (f == stdout) {
-		if (skip_stdout_flush < 0) {
-			int flush_setting = git_env_bool("GIT_FLUSH", -1);
+		static int force_flush_stdout = -1;
 
-			if (0 <= flush_setting)
-				skip_stdout_flush = !flush_setting;
-			else {
+		if (force_flush_stdout < 0) {
+			force_flush_stdout = git_env_bool("GIT_FLUSH", -1);
+			if (force_flush_stdout < 0) {
 				struct stat st;
 				if (fstat(fileno(stdout), &st))
-					skip_stdout_flush = 0;
+					force_flush_stdout = 1;
 				else
-					skip_stdout_flush = S_ISREG(st.st_mode);
+					force_flush_stdout = !S_ISREG(st.st_mode);
 			}
 		}
-		if (skip_stdout_flush && !ferror(f))
+		if (!force_flush_stdout && !ferror(f))
 			return;
 	}
 	if (fflush(f)) {
Junio C Hamano· Feb 13, 2024, 19:48 UTC · re: Junio C Hamano · lore

Re: Bug report: Incorrect GIT_FLUSH behavior in 2.43.1 (regression and breaking)

Junio C Hamano <gitster@pobox.com> writes:
> Unfortunately the minimum fix is already in 'next', so let me turn
> what you wrote into an update relative to that.  I'll assume your
> patch in the discussion is signed-off already?

Nah, my mistake. The topic still is outside 'next', so I'll replace it with the attached while queuing.

Thanks.
------- >8 ------------- >8 ------------- >8 -------
Subject: [PATCH] write-or-die: fix the polarity of GIT_FLUSH environment variable

When GIT_FLUSH is set to 1, true, on, yes, then we should disable skip_stdout_flush, but the conversion somehow did the opposite.

With the understanding of the original motivation behind "skip" in 06f59e9f (Don't fflush(stdout) when it's not helpful, 2007-06-29), we can sympathize with the current naming (we wanted to avoid useless flushing of stdout by default, with an escape hatch to always flush), but it is still not a good excuse.

Retire the "skip_stdout_flush" variable and replace it with "flush_stdout" that tells if we do or do not want to run fflush().

Reported-by: Xiaoguang WANG <wxiaoguang@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 write-or-die.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/write-or-die.c b/write-or-die.c
index 3942152865..01a9a51fa2 100644
--- a/write-or-die.c
+++ b/write-or-die.c
@@ -18,20 +18,20 @@
  */
 void maybe_flush_or_die(FILE *f, const char *desc)
 {
-	static int skip_stdout_flush = -1;
-
 	if (f == stdout) {
-		if (skip_stdout_flush < 0) {
-			skip_stdout_flush = git_env_bool("GIT_FLUSH", -1);
-			if (skip_stdout_flush < 0) {
+		static int force_flush_stdout = -1;
+
+		if (force_flush_stdout < 0) {
+			force_flush_stdout = git_env_bool("GIT_FLUSH", -1);
+			if (force_flush_stdout < 0) {
 				struct stat st;
 				if (fstat(fileno(stdout), &st))
-					skip_stdout_flush = 0;
+					force_flush_stdout = 1;
 				else
-					skip_stdout_flush = S_ISREG(st.st_mode);
+					force_flush_stdout = !S_ISREG(st.st_mode);
 			}
 		}
-		if (skip_stdout_flush && !ferror(f))
+		if (!force_flush_stdout && !ferror(f))
 			return;
 	}
 	if (fflush(f)) {
-- 
2.44.0-rc0-46-g2996f11c1d
Phillip Wood· Feb 14, 2024, 10:57 UTC · re: Junio C Hamano · lore

Re: Bug report: Incorrect GIT_FLUSH behavior in 2.43.1 (regression and breaking)

Hi Junio
On 13/02/2024 19:48, Junio C Hamano wrote:
Show 8 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
> 
>> Unfortunately the minimum fix is already in 'next', so let me turn
>> what you wrote into an update relative to that.  I'll assume your
>> patch in the discussion is signed-off already?
> 
> Nah, my mistake.  The topic still is outside 'next', so I'll replace
> it with the attached while queuing.
 >
Show 16 quoted lines
> Thanks.
> 
> ------- >8 ------------- >8 ------------- >8 -------
> Subject: [PATCH] write-or-die: fix the polarity of GIT_FLUSH environment variable
> 
> When GIT_FLUSH is set to 1, true, on, yes, then we should disable
> skip_stdout_flush, but the conversion somehow did the opposite.
> 
> With the understanding of the original motivation behind "skip" in
> 06f59e9f (Don't fflush(stdout) when it's not helpful, 2007-06-29),
> we can sympathize with the current naming (we wanted to avoid
> useless flushing of stdout by default, with an escape hatch to
> always flush), but it is still not a good excuse.
> 
> Retire the "skip_stdout_flush" variable and replace it with "flush_stdout"
> that tells if we do or do not want to run fflush().

I think the patch looks good and the commit message nicely explains why we want to change the name of the variable.

Best Wishes
Phillip
Show 40 quoted lines
> Reported-by: Xiaoguang WANG <wxiaoguang@gmail.com>
> Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>   write-or-die.c | 16 ++++++++--------
>   1 file changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/write-or-die.c b/write-or-die.c
> index 3942152865..01a9a51fa2 100644
> --- a/write-or-die.c
> +++ b/write-or-die.c
> @@ -18,20 +18,20 @@
>    */
>   void maybe_flush_or_die(FILE *f, const char *desc)
>   {
> -	static int skip_stdout_flush = -1;
> -
>   	if (f == stdout) {
> -		if (skip_stdout_flush < 0) {
> -			skip_stdout_flush = git_env_bool("GIT_FLUSH", -1);
> -			if (skip_stdout_flush < 0) {
> +		static int force_flush_stdout = -1;
> +
> +		if (force_flush_stdout < 0) {
> +			force_flush_stdout = git_env_bool("GIT_FLUSH", -1);
> +			if (force_flush_stdout < 0) {
>   				struct stat st;
>   				if (fstat(fileno(stdout), &st))
> -					skip_stdout_flush = 0;
> +					force_flush_stdout = 1;
>   				else
> -					skip_stdout_flush = S_ISREG(st.st_mode);
> +					force_flush_stdout = !S_ISREG(st.st_mode);
>   			}
>   		}
> -		if (skip_stdout_flush && !ferror(f))
> +		if (!force_flush_stdout && !ferror(f))
>   			return;
>   	}
>   	if (fflush(f)) {

← back to recent threads