|
@@ -1,140 +0,0 @@
|
1
|
|
-From 27187ab56a2f1104818c2f21c5139c1edd8b838f Mon Sep 17 00:00:00 2001
|
2
|
|
-From: Willy Tarreau <w@1wt.eu>
|
3
|
|
-Date: Thu, 2 Jul 2015 12:50:23 +0200
|
4
|
|
-Subject: BUG/MAJOR: buffers: make the buffer_slow_realign() function respect
|
5
|
|
- output data
|
6
|
|
-
|
7
|
|
-The function buffer_slow_realign() was initially designed for requests
|
8
|
|
-only and did not consider pending outgoing data. This causes a problem
|
9
|
|
-when called on responses where data remain in the buffer, which may
|
10
|
|
-happen with pipelined requests when the client is slow to read data.
|
11
|
|
-
|
12
|
|
-The user-visible effect is that if less than <maxrewrite> bytes are
|
13
|
|
-present in the buffer from a previous response and these bytes cross
|
14
|
|
-the <maxrewrite> boundary close to the end of the buffer, then a new
|
15
|
|
-response will cause a realign and will destroy these pending data and
|
16
|
|
-move the pointer to what's believed to contain pending output data.
|
17
|
|
-Thus the client receives the crap that lies in the buffer instead of
|
18
|
|
-the original output bytes.
|
19
|
|
-
|
20
|
|
-This new implementation now properly realigns everything including the
|
21
|
|
-outgoing data which are moved to the end of the buffer while the input
|
22
|
|
-data are moved to the beginning.
|
23
|
|
-
|
24
|
|
-This implementation still uses a buffer-to-buffer copy which is not
|
25
|
|
-optimal in terms of performance and which should be replaced by a
|
26
|
|
-buffer switch later.
|
27
|
|
-
|
28
|
|
-Prior to this patch, the following script would return different hashes
|
29
|
|
-on each round when run from a 100 Mbps-connected machine :
|
30
|
|
-
|
31
|
|
- i=0
|
32
|
|
- while usleep 100000; do
|
33
|
|
- echo round $((i++))
|
34
|
|
- set -- $(nc6 0 8001 < 1kreq5k.txt | grep -v '^[0-9A-Z]' | md5sum)
|
35
|
|
- if [ "$1" != "3861afbb6566cd48740ce01edc426020" ]; then echo $1;break;fi
|
36
|
|
- done
|
37
|
|
-
|
38
|
|
-The file contains 1000 times this request with "Connection: close" on the
|
39
|
|
-last one :
|
40
|
|
-
|
41
|
|
- GET /?s=5k&R=1 HTTP/1.1
|
42
|
|
-
|
43
|
|
-The config is very simple :
|
44
|
|
-
|
45
|
|
- global
|
46
|
|
- tune.bufsize 16384
|
47
|
|
- tune.maxrewrite 8192
|
48
|
|
-
|
49
|
|
- defaults
|
50
|
|
- mode http
|
51
|
|
- timeout client 10s
|
52
|
|
- timeout server 5s
|
53
|
|
- timeout connect 3s
|
54
|
|
-
|
55
|
|
- listen px
|
56
|
|
- bind :8001
|
57
|
|
- option http-server-close
|
58
|
|
- server s1 127.0.0.1:8000
|
59
|
|
-
|
60
|
|
-And httpterm-1.7.2 is used as the server on port 8000.
|
61
|
|
-
|
62
|
|
-After the fix, 1 million requests were sent and all returned the same
|
63
|
|
-contents.
|
64
|
|
-
|
65
|
|
-Many thanks to Charlie Smurthwaite of atechmedia.com for his precious
|
66
|
|
-help on this issue, which would not have been diagnosed without his
|
67
|
|
-very detailed traces and numerous tests.
|
68
|
|
-
|
69
|
|
-The patch must be backported to 1.5 which is where the bug was introduced.
|
70
|
|
----
|
71
|
|
- src/buffer.c | 49 +++++++++++++++++++++++++++++--------------------
|
72
|
|
- 1 file changed, 29 insertions(+), 20 deletions(-)
|
73
|
|
-
|
74
|
|
-diff --git a/src/buffer.c b/src/buffer.c
|
75
|
|
-index 3c7f6cc..b083768 100644
|
76
|
|
---- a/src/buffer.c
|
77
|
|
-+++ b/src/buffer.c
|
78
|
|
-@@ -136,30 +136,39 @@ int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
|
79
|
|
- return delta;
|
80
|
|
- }
|
81
|
|
-
|
82
|
|
--/* This function realigns input data in a possibly wrapping buffer so that it
|
83
|
|
-- * becomes contiguous and starts at the beginning of the buffer area. The
|
84
|
|
-- * function may only be used when the buffer's output is empty.
|
85
|
|
-+/* This function realigns a possibly wrapping buffer so that the input part is
|
86
|
|
-+ * contiguous and starts at the beginning of the buffer and the output part
|
87
|
|
-+ * ends at the end of the buffer. This provides the best conditions since it
|
88
|
|
-+ * allows the largest inputs to be processed at once and ensures that once the
|
89
|
|
-+ * output data leaves, the whole buffer is available at once.
|
90
|
|
- */
|
91
|
|
- void buffer_slow_realign(struct buffer *buf)
|
92
|
|
- {
|
93
|
|
-- /* two possible cases :
|
94
|
|
-- * - the buffer is in one contiguous block, we move it in-place
|
95
|
|
-- * - the buffer is in two blocks, we move it via the swap_buffer
|
96
|
|
-- */
|
97
|
|
-- if (buf->i) {
|
98
|
|
-- int block1 = buf->i;
|
99
|
|
-- int block2 = 0;
|
100
|
|
-- if (buf->p + buf->i > buf->data + buf->size) {
|
101
|
|
-- /* non-contiguous block */
|
102
|
|
-- block1 = buf->data + buf->size - buf->p;
|
103
|
|
-- block2 = buf->p + buf->i - (buf->data + buf->size);
|
104
|
|
-- }
|
105
|
|
-- if (block2)
|
106
|
|
-- memcpy(swap_buffer, buf->data, block2);
|
107
|
|
-- memmove(buf->data, buf->p, block1);
|
108
|
|
-- if (block2)
|
109
|
|
-- memcpy(buf->data + block1, swap_buffer, block2);
|
110
|
|
-+ int block1 = buf->o;
|
111
|
|
-+ int block2 = 0;
|
112
|
|
-+
|
113
|
|
-+ /* process output data in two steps to cover wrapping */
|
114
|
|
-+ if (block1 > buf->p - buf->data) {
|
115
|
|
-+ block2 = buf->p - buf->data;
|
116
|
|
-+ block1 -= block2;
|
117
|
|
- }
|
118
|
|
-+ memcpy(swap_buffer + buf->size - buf->o, bo_ptr(buf), block1);
|
119
|
|
-+ memcpy(swap_buffer + buf->size - block2, buf->data, block2);
|
120
|
|
-+
|
121
|
|
-+ /* process input data in two steps to cover wrapping */
|
122
|
|
-+ block1 = buf->i;
|
123
|
|
-+ block2 = 0;
|
124
|
|
-+
|
125
|
|
-+ if (block1 > buf->data + buf->size - buf->p) {
|
126
|
|
-+ block1 = buf->data + buf->size - buf->p;
|
127
|
|
-+ block2 = buf->i - block1;
|
128
|
|
-+ }
|
129
|
|
-+ memcpy(swap_buffer, bi_ptr(buf), block1);
|
130
|
|
-+ memcpy(swap_buffer + block1, buf->data, block2);
|
131
|
|
-+
|
132
|
|
-+ /* reinject changes into the buffer */
|
133
|
|
-+ memcpy(buf->data, swap_buffer, buf->i);
|
134
|
|
-+ memcpy(buf->data + buf->size - buf->o, swap_buffer + buf->size - buf->o, buf->o);
|
135
|
|
-
|
136
|
|
- buf->p = buf->data;
|
137
|
|
- }
|
138
|
|
-1.7.12.1
|
139
|
|
-
|