Mercurial > hg > nginx
annotate src/http/v2/ngx_http_v2_encode.c @ 7951:c7a8bdf5af55
Changed ngx_chain_update_chains() to test tag first (ticket #2248).
Without this change, aio used with HTTP/2 can result in connection hang,
as observed with "aio threads; aio_write on;" and proxying (ticket #2248).
The problem is that HTTP/2 updates buffers outside of the output filters
(notably, marks them as sent), and then posts a write event to call
output filters. If a filter does not call the next one for some reason
(for example, because of an AIO operation in progress), this might
result in a state when the owner of a buffer already called
ngx_chain_update_chains() and can reuse the buffer, while the same buffer
is still sitting in the busy chain of some other filter.
In the particular case a buffer was sitting in output chain's ctx->busy,
and was reused by event pipe. Output chain's ctx->busy was permanently
blocked by it, and this resulted in connection hang.
Fix is to change ngx_chain_update_chains() to skip buffers from other
modules unconditionally, without trying to wait for these buffers to
become empty.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sat, 30 Oct 2021 02:39:19 +0300 |
parents | 87e9e4aabf1b |
children | 336084ff943b |
rev | line source |
---|---|
7229
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
1 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
2 /* |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
3 * Copyright (C) Nginx, Inc. |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
4 * Copyright (C) Valentin V. Bartenev |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
5 */ |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
6 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
7 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
8 #include <ngx_config.h> |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
9 #include <ngx_core.h> |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
10 #include <ngx_http.h> |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
11 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
12 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
13 static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
14 ngx_uint_t value); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
15 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
16 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
17 u_char * |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
18 ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
19 ngx_uint_t lower) |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
20 { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
21 size_t hlen; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
22 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
23 hlen = ngx_http_v2_huff_encode(src, len, tmp, lower); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
24 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
25 if (hlen > 0) { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
26 *dst = NGX_HTTP_V2_ENCODE_HUFF; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
27 dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), hlen); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
28 return ngx_cpymem(dst, tmp, hlen); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
29 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
30 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
31 *dst = NGX_HTTP_V2_ENCODE_RAW; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
32 dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), len); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
33 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
34 if (lower) { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
35 ngx_strlow(dst, src, len); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
36 return dst + len; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
37 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
38 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
39 return ngx_cpymem(dst, src, len); |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
40 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
41 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
42 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
43 static u_char * |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
44 ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value) |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
45 { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
46 if (value < prefix) { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
47 *pos++ |= value; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
48 return pos; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
49 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
50 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
51 *pos++ |= prefix; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
52 value -= prefix; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
53 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
54 while (value >= 128) { |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
55 *pos++ = value % 128 + 128; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
56 value /= 128; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
57 } |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
58 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
59 *pos++ = (u_char) value; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
60 |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
61 return pos; |
87e9e4aabf1b
HTTP/2: externalized various constants and interfaces.
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff
changeset
|
62 } |