Mercurial > hg > nginx-quic
comparison src/stream/ngx_stream_core_module.c @ 7345:fe767c99c2ad
Stream: avoid potential infinite loop at preread phase.
Previously the preread phase code ignored NGX_AGAIN value returned from
c->recv() and relied only on c->read->ready. But this flag is not reliable and
should only be checked for optimization purposes. For example, when using
SSL, c->read->ready may be set when no input is available. This can lead to
calling preread handler infinitely in a loop.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 29 Aug 2018 15:56:42 +0300 |
parents | 7f955d3b9a0d |
children | 4f9b72a229c1 |
comparison
equal
deleted
inserted
replaced
7344:5f6d2e102f4c | 7345:fe767c99c2ad |
---|---|
247 rc = NGX_STREAM_OK; | 247 rc = NGX_STREAM_OK; |
248 break; | 248 break; |
249 } | 249 } |
250 | 250 |
251 if (!c->read->ready) { | 251 if (!c->read->ready) { |
252 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { | 252 break; |
253 rc = NGX_ERROR; | |
254 break; | |
255 } | |
256 | |
257 if (!c->read->timer_set) { | |
258 ngx_add_timer(c->read, cscf->preread_timeout); | |
259 } | |
260 | |
261 c->read->handler = ngx_stream_session_handler; | |
262 | |
263 return NGX_OK; | |
264 } | 253 } |
265 | 254 |
266 n = c->recv(c, c->buffer->last, size); | 255 n = c->recv(c, c->buffer->last, size); |
267 | 256 |
268 if (n == NGX_ERROR) { | 257 if (n == NGX_ERROR || n == 0) { |
269 rc = NGX_STREAM_OK; | 258 rc = NGX_STREAM_OK; |
270 break; | 259 break; |
271 } | 260 } |
272 | 261 |
273 if (n > 0) { | 262 if (n == NGX_AGAIN) { |
274 c->buffer->last += n; | 263 break; |
275 } | 264 } |
265 | |
266 c->buffer->last += n; | |
276 | 267 |
277 rc = ph->handler(s); | 268 rc = ph->handler(s); |
269 } | |
270 | |
271 if (rc == NGX_AGAIN) { | |
272 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { | |
273 ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); | |
274 return NGX_OK; | |
275 } | |
276 | |
277 if (!c->read->timer_set) { | |
278 ngx_add_timer(c->read, cscf->preread_timeout); | |
279 } | |
280 | |
281 c->read->handler = ngx_stream_session_handler; | |
282 | |
283 return NGX_OK; | |
278 } | 284 } |
279 | 285 |
280 if (c->read->timer_set) { | 286 if (c->read->timer_set) { |
281 ngx_del_timer(c->read); | 287 ngx_del_timer(c->read); |
282 } | 288 } |