Submitted By: Jim Gifford (jim at cross-lfs dot org) Date: 2009-01-04 Initial Package Version: 1.21 Origin: Tar Bug List Upstream Status: Applied Description: http://lists.gnu.org/archive/html/bug-tar/2008-12/msg00028.html diff -Naur tar-1.21.orig/src/buffer.c tar-1.21/src/buffer.c --- tar-1.21.orig/src/buffer.c 2008-11-30 04:30:29.000000000 -0800 +++ tar-1.21/src/buffer.c 2009-01-04 20:04:57.000000000 -0800 @@ -848,6 +848,8 @@ flush_archive (); } + sys_drain_input_pipe (); + compute_duration (); if (verify_option) verify_volume (); @@ -855,7 +857,7 @@ if (rmtclose (archive) != 0) close_error (*archive_name_cursor); - sys_wait_for_child (child_pid, hit_eof); + sys_wait_for_child (child_pid); tar_stat_destroy (¤t_stat_info); if (save_name) diff -Naur tar-1.21.orig/src/common.h tar-1.21/src/common.h --- tar-1.21.orig/src/common.h 2008-11-30 04:30:29.000000000 -0800 +++ tar-1.21/src/common.h 2009-01-04 20:04:57.000000000 -0800 @@ -699,7 +699,8 @@ void sys_detect_dev_null_output (void); void sys_save_archive_dev_ino (void); -void sys_wait_for_child (pid_t, bool); +void sys_drain_input_pipe (void); +void sys_wait_for_child (pid_t); void sys_spawn_shell (void); bool sys_compare_uid (struct stat *a, struct stat *b); bool sys_compare_gid (struct stat *a, struct stat *b); diff -Naur tar-1.21.orig/src/system.c tar-1.21/src/system.c --- tar-1.21.orig/src/system.c 2008-11-30 04:30:30.000000000 -0800 +++ tar-1.21/src/system.c 2009-01-04 20:04:57.000000000 -0800 @@ -1,7 +1,6 @@ /* System-dependent calls for tar. - Copyright (C) 2003, 2004, 2005, 2006, 2007, - 2008 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -52,7 +51,12 @@ } void -sys_wait_for_child (pid_t child_pid, bool eof) +sys_drain_input_pipe (void) +{ +} + +void +sys_wait_for_child (pid_t child_pid) { } @@ -156,8 +160,26 @@ && archive_stat.st_ino == dev_null_stat.st_ino)); } +/* Manage to fully drain a pipe we might be reading, so to not break it on + the producer after the EOF block. FIXME: one of these days, GNU tar + might become clever enough to just stop working, once there is no more + work to do, we might have to revise this area in such time. */ + +void +sys_drain_input_pipe (void) +{ + size_t r; + + if (access_mode == ACCESS_READ + && ! _isrmt (archive) + && (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode))) + while ((r = rmtread (archive, record_start->buffer, record_size)) != 0 + && r != SAFE_READ_ERROR) + continue; +} + void -sys_wait_for_child (pid_t child_pid, bool eof) +sys_wait_for_child (pid_t child_pid) { if (child_pid) { @@ -171,11 +193,8 @@ } if (WIFSIGNALED (wait_status)) - { - int sig = WTERMSIG (wait_status); - if (!(!eof && sig == SIGPIPE)) - ERROR ((0, 0, _("Child died with signal %d"), sig)); - } + ERROR ((0, 0, _("Child died with signal %d"), + WTERMSIG (wait_status))); else if (WEXITSTATUS (wait_status) != 0) ERROR ((0, 0, _("Child returned status %d"), WEXITSTATUS (wait_status)));