@@ -235,15 +235,12 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
235
235
uint16_t old_context ;
236
236
ngx_http_cleanup_t * cln ;
237
237
ngx_chain_t * out ;
238
+ ngx_chain_t * cl , * ln , * * ll ;
238
239
ngx_http_lua_main_conf_t * lmcf ;
239
240
240
241
ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
241
242
"lua body filter for user lua code, uri \"%V\"" , & r -> uri );
242
243
243
- if (in == NULL ) {
244
- return ngx_http_next_body_filter (r , in );
245
- }
246
-
247
244
llcf = ngx_http_get_module_loc_conf (r , ngx_http_lua_module );
248
245
249
246
if (llcf -> body_filter_handler == NULL ) {
@@ -272,6 +269,50 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
272
269
return NGX_OK ;
273
270
}
274
271
272
+ if (in != NULL ) {
273
+ ll = & ctx -> in_bufs ;
274
+ while (* ll != NULL ) {
275
+ ll = & (* ll )-> next ;
276
+ }
277
+
278
+ for (ln = in ; ln != NULL ; ln = ln -> next ) {
279
+ cl = ngx_alloc_chain_link (r -> pool );
280
+ if (cl == NULL ) {
281
+ return NGX_ERROR ;
282
+ }
283
+
284
+ cl -> buf = ln -> buf ;
285
+ cl -> next = NULL ;
286
+ * ll = cl ;
287
+ ll = & cl -> next ;
288
+ }
289
+ }
290
+
291
+ if (ctx -> last_body_filter_rc == NGX_AGAIN && ctx -> busy_bufs != NULL ) {
292
+ /* Socket write buffer was full on last write.
293
+ * Try to write the remain data, if still can not write
294
+ * do not execute body_filter_by_lua otherwise the `in` chain will be
295
+ * replaced by new content from lua and buf of `in` mark as consumed.
296
+ * And then ngx_output_chain will call the filter chain again which
297
+ * make all the data cached in the memory and long ngx_chain_t link
298
+ * cause CPU 100%.
299
+ */
300
+ rc = ngx_http_next_body_filter (r , NULL );
301
+ ctx -> last_body_filter_rc = rc ;
302
+
303
+ if (rc == NGX_ERROR ) {
304
+ return rc ;
305
+ }
306
+
307
+ out = NULL ;
308
+ ngx_chain_update_chains (r -> pool ,
309
+ & ctx -> free_bufs , & ctx -> busy_bufs , & out ,
310
+ (ngx_buf_tag_t ) & ngx_http_lua_module );
311
+ if (rc != NGX_OK ) {
312
+ return rc ;
313
+ }
314
+ }
315
+
275
316
if (ctx -> cleanup == NULL ) {
276
317
cln = ngx_http_cleanup_add (r , 0 );
277
318
if (cln == NULL ) {
@@ -286,6 +327,9 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
286
327
old_context = ctx -> context ;
287
328
ctx -> context = NGX_HTTP_LUA_CONTEXT_BODY_FILTER ;
288
329
330
+ in = ctx -> in_bufs ;
331
+ ctx -> in_bufs = NULL ;
332
+
289
333
dd ("calling body filter handler" );
290
334
rc = llcf -> body_filter_handler (r , in );
291
335
@@ -300,8 +344,21 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
300
344
lmcf = ngx_http_get_module_main_conf (r , ngx_http_lua_module );
301
345
out = lmcf -> body_filter_chain ;
302
346
303
- if (in == out ) {
304
- return ngx_http_next_body_filter (r , in );
347
+ if (in != out ) {
348
+ /* content of body was replaced in ngx_http_lua_body_filter_param_set
349
+ * and the buffer was marked as consumed.
350
+ */
351
+ for (cl = in ; cl != NULL ; cl = ln ) {
352
+ ln = cl -> next ;
353
+ if (ngx_buf_size (cl -> buf ) == 0 ) {
354
+ ngx_free_chain (r -> pool , cl );
355
+
356
+ } else {
357
+ ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 ,
358
+ "chain link was not marked as consumed" );
359
+ return NGX_ERROR ;
360
+ }
361
+ }
305
362
}
306
363
307
364
if (out == NULL ) {
@@ -316,6 +373,8 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
316
373
return NGX_ERROR ;
317
374
}
318
375
376
+ ctx -> last_body_filter_rc = rc ;
377
+
319
378
ngx_chain_update_chains (r -> pool ,
320
379
& ctx -> free_bufs , & ctx -> busy_bufs , & out ,
321
380
(ngx_buf_tag_t ) & ngx_http_lua_module );
@@ -622,3 +681,5 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r,
622
681
}
623
682
624
683
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */
684
+
685
+
0 commit comments