Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 May 2010 10:17:54 -0700
From:      Tim Kientzle <kientzle@freebsd.org>
To:        Anonymous <swell.k@gmail.com>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org
Subject:   Re: svn commit: r207790 - head/usr.bin/tar
Message-ID:  <4BF811C2.4050901@freebsd.org>
In-Reply-To: <86mxvsxtjh.fsf@gmail.com>
References:  <201005081628.o48GSM9s067363__30886.3841965378$1273336146$gmane$org@svn.freebsd.org>	<86aas3oc8b.fsf@gmail.com>	<4BF059FF.8050002__30617.9139217877$1274042897$gmane$org@freebsd.org>	<861vdaakkf.fsf@gmail.com> <86mxvsxtjh.fsf@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------080204080707060602010606
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Ah, yes.  I did forget to add an EINTR check to the write side.

Attached patch should fix "tar cf"

Thanks for your careful testing...


Anonymous wrote:
> Anonymous <swell.k@gmail.com> writes:
> 
>> Tim Kientzle <kientzle@freebsd.org> writes:
>>
>>> Please try the attached patch and let me know if it fixes it for you...
>>>
>>> Cheers,
>>>
>>> Tim
>> [...]
>>
>> It fixes the issue. Thanks.
> 
> I'm afraid not. Similar issue affects `tar cf - blah | tar xf -'.
> It's a little bit harder to reproduce. Caught after using pkg_add(1).
> 
>   # pkg_add gtk-2.20.1_1.tbz
>   load: 0.21  cmd: bsdtar 3351 [running] 0.06r 0.02u 0.00s 1% 6348k
>   In: 307200 bytes, compression 76%;  Out: 161 files, 1316787 bytes
>   Current: include/gtk-2.0/gtk/gtklabel.h (8627 bytes)
>   load: 0.16  cmd: bsdtar 3354 [tx->tx_quiesce_done_cv)] 4.08r 0.00u 0.14s 1% 2712k
>   In: 544 files, 36359168 bytes; Out: 36352000 bytes, compression 0%
>   Current: share/locale/hi/LC_MESSAGES/gtk20-properties.mo (131072/234342 bytes)
>   load: 0.16  cmd: bsdtar 3354 [tx->tx_quiesce_done_cv)] 4.86r 0.00u 0.14s 1% 2712k
>   tar: Write error
>   In: 36341760 bytes, compression 0%;  Out: 544 files, 36341760 bytes
>   Current: share/locale/hi/LC_MESSAGES/gtk20-properties.mo (234342 bytes)
>   share/locale/hi/LC_MESSAGES/gtk20-properties.mo: Truncated tar archive
>   tar: Error exit delayed from previous errors.
>   pkg_add: leave_playpen: can't chdir back to ''
>   zsh: exit 2     sudo -E pkg_add gtk-x11-2.20.1_1.tbz
> 
> Workaround is the same - svn diff -c207790 | patch -R
> 
> --
> I don't remember svn revision (newvers.sh doesn't work here). But it was
> after you committed that patch.
> 
>   $ uname -vm
>   FreeBSD 9.0-CURRENT #0: Fri May 21 15:32:05 UTC 2010 ...:.../PHOENIX  amd64
> 
> 

--------------080204080707060602010606
Content-Type: text/x-patch;
 name="libarchive_write_handle_eintr.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="libarchive_write_handle_eintr.patch"

Index: archive_write_open_fd.c
===================================================================
--- archive_write_open_fd.c	(revision 2413)
+++ archive_write_open_fd.c	(working copy)
@@ -51,7 +51,6 @@
 #include "archive.h"
 
 struct write_fd_data {
-	off_t		offset;
 	int		fd;
 };
 
@@ -122,12 +121,16 @@
 	ssize_t	bytesWritten;
 
 	mine = (struct write_fd_data *)client_data;
-	bytesWritten = write(mine->fd, buff, length);
-	if (bytesWritten <= 0) {
-		archive_set_error(a, errno, "Write error");
-		return (-1);
+	for (;;) {
+		bytesWritten = write(mine->fd, buff, length);
+		if (bytesWritten <= 0) {
+			if (errno == EINTR)
+				continue;
+			archive_set_error(a, errno, "Write error");
+			return (-1);
+		}
+		return (bytesWritten);
 	}
-	return (bytesWritten);
 }
 
 static int
Index: archive_write_open_file.c
===================================================================
--- archive_write_open_file.c	(revision 2413)
+++ archive_write_open_file.c	(working copy)
@@ -86,12 +86,16 @@
 	size_t	bytesWritten;
 
 	mine = client_data;
-	bytesWritten = fwrite(buff, 1, length, mine->f);
-	if (bytesWritten < length) {
-		archive_set_error(a, errno, "Write error");
-		return (-1);
+	for (;;) {
+		bytesWritten = fwrite(buff, 1, length, mine->f);
+		if (bytesWritten <= 0) {
+			if (errno == EINTR)
+				continue;
+			archive_set_error(a, errno, "Write error");
+			return (-1);
+		}
+		return (bytesWritten);
 	}
-	return (bytesWritten);
 }
 
 static int
Index: archive_write_open_filename.c
===================================================================
--- archive_write_open_filename.c	(revision 2413)
+++ archive_write_open_filename.c	(working copy)
@@ -142,12 +142,16 @@
 	ssize_t	bytesWritten;
 
 	mine = (struct write_file_data *)client_data;
-	bytesWritten = write(mine->fd, buff, length);
-	if (bytesWritten <= 0) {
-		archive_set_error(a, errno, "Write error");
-		return (-1);
+	for (;;) {
+		bytesWritten = write(mine->fd, buff, length);
+		if (bytesWritten <= 0) {
+			if (errno == EINTR)
+				continue;
+			archive_set_error(a, errno, "Write error");
+			return (-1);
+		}
+		return (bytesWritten);
 	}
-	return (bytesWritten);
 }
 
 static int
Index: archive_write.c
===================================================================
--- archive_write.c	(revision 2413)
+++ archive_write.c	(working copy)
@@ -361,11 +361,20 @@
                 remaining -= to_copy;
                 /* ... if it's full, write it out. */
                 if (state->avail == 0) {
-                        bytes_written = (a->client_writer)(&a->archive,
-                            a->client_data, state->buffer, state->buffer_size);
-                        if (bytes_written <= 0)
-                                return (ARCHIVE_FATAL);
-                        /* XXX TODO: if bytes_written < state->buffer_size */
+			char *p = state->buffer;
+			size_t remaining = state->buffer_size;
+			while (remaining > 0) {
+				bytes_written = (a->client_writer)(&a->archive,
+				    a->client_data, p, remaining);
+				if (bytes_written <= 0)
+					return (ARCHIVE_FATAL);
+				if (bytes_remaining > remaining) {
+					archive_set_error(a, -1, "write overrun");
+					return (ARCHIVE_FATAL);
+				}
+				p += bytes_written;
+				remaining -= bytes_written;
+			}
                         state->next = state->buffer;
                         state->avail = state->buffer_size;
                 }

--------------080204080707060602010606--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4BF811C2.4050901>