[PATCH 2/2] run-command: handle short writes and EINTR in die_child
- From
Jonathan Nieder <jrnieder@gmail.com>
- Date
- Apr 20, 2011, 10:40 UTC
- Message-ID
- <20110420104005.GC6027@elie>
- In-Reply-To
- <20110420103319.GA6027@elie>
If start_command fails after forking and before exec finishes, there is not much use in noticing an I/O error on top of that. finish_command will notice that the child exited with nonzero status anyway. So as noted in v1.7.0.3~20^2 (run-command.c: fix build warnings on Ubuntu, 2010-01-30) and v1.7.5-rc0~29^2 (2011-03-16), it is safe to ignore errors from write in this codepath.
Even so, the result from write contains useful information: it tells us if the write was cancelled by a signal (EINTR) or was only partially completed (e.g., when writing to an almost-full pipe). Let's use write_in_full to loop until the desired number of bytes have been written (still ignoring errors if that fails).
As a happy side effect, the assignment to a dummy variable to appease gcc -D_FORTIFY_SOURCE is no longer needed. xwrite and write_in_full check the return value from write(2).
Noticed with gcc -Wunused-but-set-variable.
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> --- Changes from v1:
- rewrite the commit message from the pov of a person who does not care about this patch's origin as a brown paper bag
- drop the "if"s. If the fussy compiler/library combination was right in some strange sense after all, then it does not make much sense to take the opportunity to make another token effort to appease it as a preventative step.
run-command.c | 15 +++++++++------ 1 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/run-command.c b/run-command.c index f91e446..70e8a24 100644 --- a/run-command.c +++ b/run-command.c @@ -67,21 +67,24 @@ 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. + */ + xwrite(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); - unused = write(child_err, "fatal: ", 7); - unused = write(child_err, msg, len); - unused = write(child_err, "\n", 1); + write_in_full(child_err, "fatal: ", 7); + write_in_full(child_err, msg, len); + write_in_full(child_err, "\n", 1); exit(128); } #endif
-- 1.7.5.rc2