comparison src/http/modules/perl/ngx_http_perl_module.c @ 7524:deebe988cbd7

Perl: reworked perl module to pass ctx instead of request. This ensures that correct ctx is always available, including after filter finalization. In particular, this fixes a segmentation fault with the following configuration: location / { image_filter test; perl 'sub { my $r = shift; $r->send_http_header(); $r->print("foo\n"); $r->print("bar\n"); }'; } This also seems to be the only way to correctly handle filter finalization in various complex cases, for example, when embedded perl is used both in the original handler and in an error page called after filter finalization.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 12 Jul 2019 11:29:22 +0300
parents 919a5c6c828c
children 575480d3fd01
comparison
equal deleted inserted replaced
7523:919a5c6c828c 7524:deebe988cbd7
41 static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf, 41 static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf,
42 ngx_http_perl_main_conf_t *pmcf); 42 ngx_http_perl_main_conf_t *pmcf);
43 static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, 43 static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires,
44 ngx_log_t *log); 44 ngx_log_t *log);
45 static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, 45 static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
46 HV *nginx, SV *sub, SV **args, ngx_str_t *handler, ngx_str_t *rv); 46 ngx_http_perl_ctx_t *ctx, HV *nginx, SV *sub, SV **args,
47 ngx_str_t *handler, ngx_str_t *rv);
47 static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv); 48 static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);
48 49
49 static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf); 50 static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf);
50 static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf); 51 static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf);
51 static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf); 52 static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf);
197 ngx_http_finalize_request(r, NGX_ERROR); 198 ngx_http_finalize_request(r, NGX_ERROR);
198 return; 199 return;
199 } 200 }
200 201
201 ngx_http_set_ctx(r, ctx, ngx_http_perl_module); 202 ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
203
204 ctx->request = r;
202 } 205 }
203 206
204 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); 207 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
205 208
206 { 209 {
218 sub = ctx->next; 221 sub = ctx->next;
219 handler = &ngx_null_name; 222 handler = &ngx_null_name;
220 ctx->next = NULL; 223 ctx->next = NULL;
221 } 224 }
222 225
223 rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sub, NULL, handler, 226 rc = ngx_http_perl_call_handler(aTHX_ r, ctx, pmcf->nginx, sub, NULL,
224 NULL); 227 handler, NULL);
225 228
226 } 229 }
227 230
228 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 231 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
229 "perl handler done: %i", rc); 232 "perl handler done: %i", rc);
307 if (ctx == NULL) { 310 if (ctx == NULL) {
308 return NGX_ERROR; 311 return NGX_ERROR;
309 } 312 }
310 313
311 ngx_http_set_ctx(r, ctx, ngx_http_perl_module); 314 ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
315
316 ctx->request = r;
312 } 317 }
313 318
314 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); 319 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
315 320
316 value.data = NULL; 321 value.data = NULL;
319 324
320 dTHXa(pmcf->perl); 325 dTHXa(pmcf->perl);
321 PERL_SET_CONTEXT(pmcf->perl); 326 PERL_SET_CONTEXT(pmcf->perl);
322 PERL_SET_INTERP(pmcf->perl); 327 PERL_SET_INTERP(pmcf->perl);
323 328
324 rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, pv->sub, NULL, 329 rc = ngx_http_perl_call_handler(aTHX_ r, ctx, pmcf->nginx, pv->sub, NULL,
325 &pv->handler, &value); 330 &pv->handler, &value);
326 331
327 } 332 }
328 333
329 if (value.data) { 334 if (value.data) {
370 if (ctx == NULL) { 375 if (ctx == NULL) {
371 return NGX_ERROR; 376 return NGX_ERROR;
372 } 377 }
373 378
374 ngx_http_set_ctx(r, ctx, ngx_http_perl_module); 379 ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
380
381 ctx->request = r;
375 } 382 }
376 383
377 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); 384 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
378 385
379 ctx->ssi = ssi_ctx; 386 ctx->ssi = ssi_ctx;
428 435
429 } else { 436 } else {
430 asv = NULL; 437 asv = NULL;
431 } 438 }
432 439
433 rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv, asv, handler, 440 rc = ngx_http_perl_call_handler(aTHX_ r, ctx, pmcf->nginx, sv, asv,
434 NULL); 441 handler, NULL);
435 442
436 SvREFCNT_dec(sv); 443 SvREFCNT_dec(sv);
437 444
438 } 445 }
439 446
665 return NGX_OK; 672 return NGX_OK;
666 } 673 }
667 674
668 675
669 static ngx_int_t 676 static ngx_int_t
670 ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub, 677 ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
671 SV **args, ngx_str_t *handler, ngx_str_t *rv) 678 ngx_http_perl_ctx_t *ctx, HV *nginx, SV *sub, SV **args,
679 ngx_str_t *handler, ngx_str_t *rv)
672 { 680 {
673 SV *sv; 681 SV *sv;
674 int n, status; 682 int n, status;
675 char *line; 683 char *line;
676 u_char *err; 684 u_char *err;
685 ENTER; 693 ENTER;
686 SAVETMPS; 694 SAVETMPS;
687 695
688 PUSHMARK(sp); 696 PUSHMARK(sp);
689 697
690 sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx)); 698 sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(ctx))), nginx));
691 XPUSHs(sv); 699 XPUSHs(sv);
692 700
693 if (args) { 701 if (args) {
694 EXTEND(sp, (intptr_t) args[0]); 702 EXTEND(sp, (intptr_t) args[0]);
695 703