Mercurial > hg > nginx
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 |