run-command.c: fix build warnings on Ubuntu
PATCH 1/1 run-command.c: fix build warnings on Ubuntu
Building git on Ubuntu 9.10 warns that the return value of write(2) isn't checked. These warnings were introduced in commits:
2b541bf8 ("start_command: detect execvp failures early") a5487ddf ("start_command: report child process setup errors to the
parent's stderr")
GCC details:
$ gcc --version gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1
Silence the warnings by reading (but not making use of) the return value of write(2).
---
Although this will fix the build warnings, I am unsure if there is a better way to achieve the same result. Using "(void)write(...)" still gives warnings and I am unaware of any annotations that will silence gcc.
run-command.c | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-)
run-command.c +6 -4
@@ -67,19 +67,21 @@ static int child_notifier = -1;static void notify_parent (void ) { -write (child_notifier,"" ,1 ); +ssize_t unused; + unused =write (child_notifier,"" ,1 ); } static NORETURN void die_child(const char *err, va_list params) {char msg[4096 ]; +ssize_t unused;int len =vsnprintf (msg,sizeof (msg), err, params);if (len >sizeof (msg)) len =sizeof (msg); -write (child_err,"fatal: " ,7 ); -write (child_err, msg, len); -write (child_err,"\n" ,1 ); + unused =write (child_err,"fatal: " ,7 ); + unused =write (child_err, msg, len); + unused =write (child_err,"\n" ,1 );exit (128 ); }
Signature · 1 line
1.7.0.rc0.48.gdace5
Michael Wookey, 2010-01-29:
Quoted 10 lines
Building git on Ubuntu 9.10 warns that the return value of write(2) isn't checked.
GCC details:
$ gcc --version gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1Silence the warnings by reading (but not making use of) the return value of write(2).
Since a few weeks I get several warnings about fwrite(), currently 28 times this:
warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
gcc (Gentoo 4.3.4 p1.0, pie-10.1.5) 4.3.4
Not sure if it should be muted, that are really many places.
Markus
PATCH 1/1 run-command: prettify -D_FORTIFY_SOURCE workaround
In reply to Michael WookeyCurrent gcc + glibc with -D_FORTIFY_SOURCE try very aggressively to protect against a programming style which uses write(...) without checking the return value for errors. Even the usual hint of casting to (void) does not suppress the warning.
Sometimes when there is an output error, especially right before exit, there really is nothing to be done. The obvious solution, adopted in v1.7.0.3~20^2 (run-command.c: fix build warnings on Ubuntu, 2010-01-30), is to save the return value to a dummy variable:
ssize_t dummy; dummy = write(...);
But that (1) is ugly and (2) triggers -Wunused-but-set-variable warnings with gcc-4.6 -Wall, so we are not much better off than when we started.
Instead, use an "if" statement with an empty body to make the intent clear.
if (write(...)) ; /* yes, yes, there was an error. */
---
Hi,
Quoted 4 lines · Michael Wookey
Although this will fix the build warnings, I am unsure if there is a better way to achieve the same result. Using "(void)write(...)" still gives warnings and I am unaware of any annotations that will silence gcc.
It's been a long time (and meanwhile the patch has been working; thanks!). How about something like this?
run-command.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
run-command.c +6 -6
@@ -67,21 +67,21 @@ static int child_notifier = -1;static void notify_parent (void ) { -ssize_t unused; - unused =write (child_notifier,"" ,1 ); +if (write (child_notifier,"" ,1 )) + ;/* ok. */ } static NORETURN void die_child(const char *err, va_list params) {char msg[4096 ]; -ssize_t unused;int len =vsnprintf (msg,sizeof (msg), err, params);if (len >sizeof (msg)) len =sizeof (msg); - unused =write (child_err,"fatal: " ,7 ); - unused =write (child_err, msg, len); - unused =write (child_err,"\n" ,1 ); +if (write (child_err,"fatal: " ,7 ) || +write (child_err, msg, len) || +write (child_err,"\n" ,1 )) + ;/* ok. */ exit (128 ); }
Signature · 1 line
1.7.4.1
Re: [PATCH] run-command: prettify -D_FORTIFY_SOURCE workaround
Quoted 5 lines · Jonathan Nieder
Instead, use an "if" statement with an empty body to make the intent clear.
if (write(...)) ; /* yes, yes, there was an error. */
Yuck --- and that is not meant against your workaround, but against the compiler bogosity. The above is reasonable (for some definition of the word) and the comment makes the yuckiness tolerable by being somewhat amusing.
But your comment in the actual patch is not amusing at all.
It certainly is _not_ "ok" to see errors from write(2); we are _ignoring_ the error because at that point in the codepath there isn't any better alternative. The unusual "if ()" whose condition is solely for its side effect, with an empty body, is a strong enough sign to any reader that there is something fishy going on, and it would be helpful to the reader to hint _why_ such an unusual construct is there. It would be much better for the longer term maintainability to say at least "gcc" in the comment, i.e.
if (write(...))
; /* we know we are ignoring the error, mr gcc! */or something.
Thanks for another amusing patch.
PATCH v2 1/1 run-command: prettify -D_FORTIFY_SOURCE workaround
Current gcc + glibc with -D_FORTIFY_SOURCE try very aggressively to protect against a programming style which uses write(...) without checking the return value for errors. Even the usual hint of casting to (void) does not suppress the warning.
Sometimes when there is an output error, especially right before exit, there really is nothing to be done. The obvious solution, adopted in v1.7.0.3~20^2 (run-command.c: fix build warnings on Ubuntu, 2010-01-30), is to save the return value to a dummy variable:
ssize_t dummy; dummy = write(...);
But that (1) is ugly and (2) triggers -Wunused-but-set-variable warnings with gcc-4.6 -Wall, so we are not much better off than when we started.
Instead, use an "if" statement with an empty body to make the intent clear.
if (write(...)) ; /* yes, yes, there was an error. */
---
Quoted 9 lines · Junio C Hamano
The unusual "if ()" whose condition is solely for its side
effect, with an empty body, is a strong enough sign to any reader that there is something fishy going on, and it would be helpful to the reader to hint _why_ such an unusual construct is there. It would be much better for the longer term maintainability to say at least "gcc" in the comment, i.e.if (write(...)) ; /* we know we are ignoring the error, mr gcc! */
Very true. Some comments to that effect below.
run-command.c | 17 +++++++++++------ 1 files changed, 11 insertions(+), 6 deletions(-)
run-command.c +11 -6
@@ -67,21 +67,26 @@ static int child_notifier = -1;static void notify_parent (void ) { -ssize_t unused; - unused =write (child_notifier,"" ,1 ); +/* +* execvp failed. If possible, we'd like to let start_command +* know, so failures like ENOENT can be handled right away; but +* otherwise, finish_command will still report the error. +*/ +if (write (child_notifier,"" ,1 )) + ;/* yes, dear gcc -D_FORTIFY_SOURCE, there was an error. */ } static NORETURN void die_child(const char *err, va_list params) {char msg[4096 ]; -ssize_t unused;int len =vsnprintf (msg,sizeof (msg), err, params);if (len >sizeof (msg)) len =sizeof (msg); - unused =write (child_err,"fatal: " ,7 ); - unused =write (child_err, msg, len); - unused =write (child_err,"\n" ,1 ); +if (write (child_err,"fatal: " ,7 ) || +write (child_err, msg, len) || +write (child_err,"\n" ,1 )) + ;/* yes, gcc -D_FORTIFY_SOURCE, we know there was an error. */ exit (128 ); }
Signature · 1 line
1.7.4.1
Re: [PATCH v2] run-command: prettify -D_FORTIFY_SOURCE workaround
run-command.c static int child_notifier = -1; · line 89
Quoted 10 lines · Jonathan Nieder
static NORETURN void
die_child(const char *err, va_list params){
...run-command.c +4
-3- unused =write (child_err,"fatal: " ,7 ); - unused =write (child_err, msg, len); - unused =write (child_err,"\n" ,1 ); +if (write (child_err,"fatal: " ,7 ) || +write (child_err, msg, len) || +write (child_err,"\n" ,1 )) + ;/* yes, gcc -D_FORTIFY_SOURCE, we know there was an error. */
Strictly speaking, this changes behaviour by stopping at the first failure from write(2), but I don't think we care.
Thanks.
Re: [PATCH] run-command: prettify -D_FORTIFY_SOURCE workaround
In reply to Junio C HamanoAm 3/16/2011 6:37, schrieb Junio C Hamano:
Quoted 11 lines
It certainly is _not_ "ok" to see errors from write(2); we are _ignoring_ the error because at that point in the codepath there isn't any better alternative. The unusual "if ()" whose condition is solely for its side effect, with an empty body, is a strong enough sign to any reader that there is something fishy going on, and it would be helpful to the reader to hint _why_ such an unusual construct is there. It would be much better for the longer term maintainability to say at least "gcc" in the comment, i.e.
if (write(...)) ; /* we know we are ignoring the error, mr gcc! */
And what about compilers that warn:
';' : empty controlled statement found; is this the intent?
That's from MSVC. Perhaps:
if (write(...)) (void)0; /* we know we are ignoring the error, mr gcc! */
-- Hannes
Re: [PATCH] run-command: prettify -D_FORTIFY_SOURCE workaround
Quoted 8 lines · Johannes Sixt
And what about compilers that warn:
';' : empty controlled statement found; is this the intent?
That's from MSVC. Perhaps:
if (write(...)) (void)0; /* we know we are ignoring the error, mr gcc! */
Mm, thanks for pointing it out.
Your suggestion is part of a bigger change that imho should go in a separate patch:
$ git grep -F -e ' ; /*' origin/master | wc -l 65
I would prefer to see such a patch do
if (write(...)) {
/* ... explanation goes here ... */
}or something like
#define do_nothing() do { /* nothing */ } while (0)
if (write(...))
do_nothing(); /* ... explanation ... */but that is a small detail.