Merge lp:~akopytov/percona-xtrabackup/bug1273207-2.1 into lp:percona-xtrabackup/2.1

Proposed by Alexey Kopytov
Status: Merged
Approved by: Sergei Glushchenko
Approved revision: no longer in the source branch.
Merged at revision: 731
Proposed branch: lp:~akopytov/percona-xtrabackup/bug1273207-2.1
Merge into: lp:percona-xtrabackup/2.1
Diff against target: 180 lines (+54/-29)
6 files modified
src/common.h (+24/-0)
src/xbcrypt.c (+3/-3)
src/xbcrypt.h (+1/-2)
src/xbcrypt_read.c (+8/-8)
src/xbstream_read.c (+6/-16)
test/t/bug1273207.sh (+12/-0)
To merge this branch: bzr merge lp:~akopytov/percona-xtrabackup/bug1273207-2.1
Reviewer Review Type Date Requested Status
Sergei Glushchenko (community) g2 Approve
Review via email: mp+208729@code.launchpad.net

Description of the change

    Bug #1273207: SIGPIPE handling of xbstream

    Replaced my_read(..., MYF(MY_FULL_IO)) with a new wrapper around
    my_read() which does the same, but bails out on EOF and errors returning
    the total number of successfully read bytes. This allows to detect a
    closed pipe and abort instead of waiting infinitely for more data.

http://jenkins.percona.com/view/PXB%202.1/job/percona-xtrabackup-2.1-param/551/

To post a comment you must log in.
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

xb_crypt_read_callback returns ssize_t while xb_read_full returns size_t. Negative values do not make sense for both.
Is there any reason to conversion size_t -> ssize_t in xb_read_full?
xb_crypt_read_callback definition changed by this patch anyway, maybe would be better to return size_t from
xb_crypt_read_callback? It would also allow to get rid of a number of type conversions in xbcrypt_read.c

review: Needs Information (g2)
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Right, xb_crypt_read_callback() does not have to return ssize_t. Recommitted.

http://jenkins.percona.com/view/PXB%202.1/job/percona-xtrabackup-2.1-param/554/

Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

Approve

review: Approve (g2)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/common.h'
2--- src/common.h 2013-08-18 06:54:14 +0000
3+++ src/common.h 2014-02-28 14:37:08 +0000
4@@ -89,4 +89,28 @@
5 return (value >> 1) ? 0 : shift;
6 }
7
8+/****************************************************************************
9+Read 'len' bytes from 'fd'. It is identical to my_read(..., MYF(MY_FULL_IO)),
10+i.e. tries to combine partial reads into a single block of size 'len', except
11+that it bails out on EOF or error, and returns the number of successfully read
12+bytes instead. */
13+static inline size_t
14+xb_read_full(File fd, uchar *buf, size_t len)
15+{
16+ size_t tlen = 0;
17+ size_t tbytes;
18+
19+ while (tlen < len) {
20+ tbytes = my_read(fd, buf, len - tlen, MYF(MY_WME));
21+ if (tbytes == 0 || tbytes == MY_FILE_ERROR) {
22+ break;
23+ }
24+
25+ buf += tbytes;
26+ tlen += tbytes;
27+ }
28+
29+ return tlen;
30+}
31+
32 #endif
33
34=== modified file 'src/xbcrypt.c'
35--- src/xbcrypt.c 2013-11-27 18:43:59 +0000
36+++ src/xbcrypt.c 2014-02-28 14:37:08 +0000
37@@ -279,11 +279,11 @@
38
39
40 static
41-ssize_t
42-my_xb_crypt_read_callback(void *userdata, void *buf, size_t len, int flags)
43+size_t
44+my_xb_crypt_read_callback(void *userdata, void *buf, size_t len)
45 {
46 File* file = (File *) userdata;
47- return my_read(*file, buf, len, flags);
48+ return xb_read_full(*file, buf, len);
49 }
50
51 static
52
53=== modified file 'src/xbcrypt.h'
54--- src/xbcrypt.h 2013-11-27 18:43:59 +0000
55+++ src/xbcrypt.h 2014-02-28 14:37:08 +0000
56@@ -53,8 +53,7 @@
57 typedef struct xb_rcrypt_struct xb_rcrypt_t;
58
59 /* Callback on read for i/o, must return # of bytes read or -1 on error */
60-typedef ssize_t xb_crypt_read_callback(void *userdata,
61- void *buf, size_t len, int flags);
62+typedef size_t xb_crypt_read_callback(void *userdata, void *buf, size_t len);
63
64 xb_rcrypt_t *xb_crypt_read_open(void *userdata,
65 xb_crypt_read_callback *onread);
66
67=== modified file 'src/xbcrypt_read.c'
68--- src/xbcrypt_read.c 2013-10-17 01:00:57 +0000
69+++ src/xbcrypt_read.c 2014-02-28 14:37:08 +0000
70@@ -58,10 +58,10 @@
71 uchar *ptr;
72 ulonglong tmp;
73 ulong checksum, checksum_exp, version;
74- ssize_t bytesread;
75+ size_t bytesread;
76 xb_rcrypt_result_t result = XB_CRYPT_READ_CHUNK;
77
78- if ((bytesread = crypt->read(crypt->userdata, tmpbuf, sizeof(tmpbuf), MYF(MY_WME)))
79+ if ((bytesread = crypt->read(crypt->userdata, tmpbuf, sizeof(tmpbuf)))
80 != sizeof(tmpbuf)) {
81 if (bytesread == 0) {
82 result = XB_CRYPT_READ_EOF;
83@@ -126,8 +126,8 @@
84 *ivlen = 0;
85 *iv = 0;
86 } else {
87- if ((bytesread = crypt->read(crypt->userdata, tmpbuf, 8,
88- MYF(MY_WME))) != 8) {
89+ if ((bytesread = crypt->read(crypt->userdata, tmpbuf, 8))
90+ != 8) {
91 if (bytesread == 0) {
92 result = XB_CRYPT_READ_EOF;
93 goto err;
94@@ -176,8 +176,8 @@
95 }
96
97 if (*ivlen > 0) {
98- if (crypt->read(crypt->userdata, crypt->ivbuffer, *ivlen, MYF(MY_WME|MY_FULL_IO))
99- != (ssize_t)*ivlen) {
100+ if (crypt->read(crypt->userdata, crypt->ivbuffer, *ivlen)
101+ != *ivlen) {
102 msg("%s:%s: failed to read %lld bytes for chunk iv "
103 "at offset 0x%llx.\n", my_progname, __FUNCTION__,
104 (ulonglong)*ivlen, crypt->offset);
105@@ -212,8 +212,8 @@
106 }
107
108 if (*elen > 0) {
109- if (crypt->read(crypt->userdata, crypt->buffer, *elen, MYF(MY_WME|MY_FULL_IO))
110- != (ssize_t)*elen) {
111+ if (crypt->read(crypt->userdata, crypt->buffer, *elen)
112+ != *elen) {
113 msg("%s:%s: failed to read %lld bytes for chunk payload "
114 "at offset 0x%llx.\n", my_progname, __FUNCTION__,
115 (ulonglong)*elen, crypt->offset);
116
117=== modified file 'src/xbstream_read.c'
118--- src/xbstream_read.c 2013-08-18 06:54:14 +0000
119+++ src/xbstream_read.c 2014-02-28 14:37:08 +0000
120@@ -73,8 +73,7 @@
121
122 #define F_READ(buf,len) \
123 do { \
124- if (my_read(fd, buf, len, MYF(MY_WME|MY_FULL_IO)) == \
125- MY_FILE_ERROR) { \
126+ if (xb_read_full(fd, buf, len) < len) { \
127 msg("xb_stream_read_chunk(): my_read() failed.\n"); \
128 goto err; \
129 } \
130@@ -90,7 +89,6 @@
131 uchar tmpbuf[16];
132 uchar *ptr = tmpbuf;
133 uint pathlen;
134- size_t tlen;
135 size_t tbytes;
136 ulonglong ullval;
137 ulong checksum_exp;
138@@ -99,20 +97,12 @@
139
140 xb_ad(sizeof(tmpbuf) >= CHUNK_HEADER_CONSTANT_LEN);
141
142- /* This is the only place where we expect EOF, so read with my_read()
143- rather than F_READ() */
144- tlen = CHUNK_HEADER_CONSTANT_LEN;
145- while (tlen > 0) {
146- tbytes = my_read(fd, ptr, tlen, MYF(MY_WME));
147- if (tbytes == 0) {
148- break;
149- }
150- ptr += tbytes;
151- tlen -= tbytes;
152- }
153- if (tlen == CHUNK_HEADER_CONSTANT_LEN) {
154+ /* This is the only place where we expect EOF, so read with
155+ xb_read_full() rather than F_READ() */
156+ tbytes = xb_read_full(fd, ptr, CHUNK_HEADER_CONSTANT_LEN);
157+ if (tbytes == 0) {
158 return XB_STREAM_READ_EOF;
159- } else if (tlen > 0) {
160+ } else if (tbytes < CHUNK_HEADER_CONSTANT_LEN) {
161 msg("xb_stream_read_chunk(): unexpected end of stream at "
162 "offset 0x%llx.\n", stream->offset);
163 goto err;
164
165=== added file 'test/t/bug1273207.sh'
166--- test/t/bug1273207.sh 1970-01-01 00:00:00 +0000
167+++ test/t/bug1273207.sh 2014-02-28 14:37:08 +0000
168@@ -0,0 +1,12 @@
169+########################################################################
170+# Bug #1273207: SIGPIPE handling of xbstream
171+########################################################################
172+
173+# Create a truncated xbstream file containing only a valid chunk header
174+echo "something" > $TEST_VAR_ROOT/file
175+xbstream -c $TEST_VAR_ROOT/file | head -c 14 > $TEST_VAR_ROOT/file.xbstream
176+
177+# Write chunk header and then close the pipe. xbstream would hang before the fix
178+cat $TEST_VAR_ROOT/file.xbstream | (xbstream -x || true)
179+
180+rm -f $TEST_VAR_ROOT/{file,file.xbstream}

Subscribers

People subscribed via source and target branches

to all changes: