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.
This commit is contained in:
parent
792128b7f5
commit
1689e8a02a
3 changed files with 114 additions and 94 deletions
|
@ -15,8 +15,10 @@
|
|||
#include "XSUB.h"
|
||||
|
||||
|
||||
#define ngx_http_perl_set_request(r) \
|
||||
r = INT2PTR(ngx_http_request_t *, SvIV((SV *) SvRV(ST(0))))
|
||||
#define ngx_http_perl_set_request(r, ctx) \
|
||||
\
|
||||
ctx = INT2PTR(ngx_http_perl_ctx_t *, SvIV((SV *) SvRV(ST(0)))); \
|
||||
r = ctx->request
|
||||
|
||||
|
||||
#define ngx_http_perl_set_targ(p, len) \
|
||||
|
@ -64,14 +66,12 @@ ngx_http_perl_sv2str(pTHX_ ngx_http_request_t *r, ngx_str_t *s, SV *sv)
|
|||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_perl_output(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
ngx_http_perl_output(ngx_http_request_t *r, ngx_http_perl_ctx_t *ctx,
|
||||
ngx_buf_t *b)
|
||||
{
|
||||
ngx_chain_t out;
|
||||
ngx_chain_t out;
|
||||
#if (NGX_HTTP_SSI)
|
||||
ngx_chain_t *cl;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
|
||||
ngx_chain_t *cl;
|
||||
|
||||
if (ctx->ssi) {
|
||||
cl = ngx_alloc_chain_link(r->pool);
|
||||
|
@ -105,9 +105,10 @@ void
|
|||
status(r, code)
|
||||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
r->headers_out.status = SvIV(ST(1));
|
||||
|
||||
|
@ -121,10 +122,11 @@ void
|
|||
send_http_header(r, ...)
|
||||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
SV *sv;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
SV *sv;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
if (r->headers_out.status == 0) {
|
||||
r->headers_out.status = NGX_HTTP_OK;
|
||||
|
@ -157,9 +159,10 @@ header_only(r)
|
|||
CODE:
|
||||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
sv_upgrade(TARG, SVt_IV);
|
||||
sv_setiv(TARG, r->header_only);
|
||||
|
@ -172,9 +175,10 @@ uri(r)
|
|||
CODE:
|
||||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
ngx_http_perl_set_targ(r->uri.data, r->uri.len);
|
||||
|
||||
ST(0) = TARG;
|
||||
|
@ -185,9 +189,10 @@ args(r)
|
|||
CODE:
|
||||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
ngx_http_perl_set_targ(r->args.data, r->args.len);
|
||||
|
||||
ST(0) = TARG;
|
||||
|
@ -198,9 +203,10 @@ request_method(r)
|
|||
CODE:
|
||||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
ngx_http_perl_set_targ(r->method_name.data, r->method_name.len);
|
||||
|
||||
ST(0) = TARG;
|
||||
|
@ -211,9 +217,10 @@ remote_addr(r)
|
|||
CODE:
|
||||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
ngx_http_perl_set_targ(r->connection->addr_text.data,
|
||||
r->connection->addr_text.len);
|
||||
|
||||
|
@ -226,6 +233,7 @@ header_in(r, key)
|
|||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
SV *key;
|
||||
u_char *p, *lowcase_key, *value, sep;
|
||||
STRLEN len;
|
||||
|
@ -237,7 +245,7 @@ header_in(r, key)
|
|||
ngx_http_header_t *hh;
|
||||
ngx_http_core_main_conf_t *cmcf;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
key = ST(1);
|
||||
|
||||
|
@ -374,13 +382,12 @@ has_request_body(r, next)
|
|||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
if (r->headers_in.content_length_n <= 0 && !r->headers_in.chunked) {
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
|
||||
ctx->next = SvRV(ST(1));
|
||||
|
||||
r->request_body_in_single_buf = 1;
|
||||
|
@ -404,13 +411,14 @@ request_body(r)
|
|||
CODE:
|
||||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
u_char *p, *data;
|
||||
size_t len;
|
||||
ngx_buf_t *buf;
|
||||
ngx_chain_t *cl;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
u_char *p, *data;
|
||||
size_t len;
|
||||
ngx_buf_t *buf;
|
||||
ngx_chain_t *cl;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
if (r->request_body == NULL
|
||||
|| r->request_body->temp_file
|
||||
|
@ -465,9 +473,10 @@ request_body_file(r)
|
|||
CODE:
|
||||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
if (r->request_body == NULL || r->request_body->temp_file == NULL) {
|
||||
XSRETURN_UNDEF;
|
||||
|
@ -483,9 +492,10 @@ void
|
|||
discard_request_body(r)
|
||||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
ngx_http_discard_request_body(r);
|
||||
|
||||
|
@ -494,12 +504,13 @@ void
|
|||
header_out(r, key, value)
|
||||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
SV *key;
|
||||
SV *value;
|
||||
ngx_table_elt_t *header;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
SV *key;
|
||||
SV *value;
|
||||
ngx_table_elt_t *header;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
key = ST(1);
|
||||
value = ST(2);
|
||||
|
@ -542,13 +553,12 @@ filename(r)
|
|||
CODE:
|
||||
|
||||
dXSTARG;
|
||||
size_t root;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
size_t root;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
|
||||
if (ctx->filename.data) {
|
||||
goto done;
|
||||
}
|
||||
|
@ -571,15 +581,16 @@ void
|
|||
print(r, ...)
|
||||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
SV *sv;
|
||||
int i;
|
||||
u_char *p;
|
||||
size_t size;
|
||||
STRLEN len;
|
||||
ngx_buf_t *b;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
SV *sv;
|
||||
int i;
|
||||
u_char *p;
|
||||
size_t size;
|
||||
STRLEN len;
|
||||
ngx_buf_t *b;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
if (items == 2) {
|
||||
|
||||
|
@ -660,7 +671,7 @@ print(r, ...)
|
|||
|
||||
out:
|
||||
|
||||
(void) ngx_http_perl_output(r, b);
|
||||
(void) ngx_http_perl_output(r, ctx, b);
|
||||
|
||||
|
||||
void
|
||||
|
@ -668,6 +679,7 @@ sendfile(r, filename, offset = -1, bytes = 0)
|
|||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
char *filename;
|
||||
off_t offset;
|
||||
size_t bytes;
|
||||
|
@ -676,7 +688,7 @@ sendfile(r, filename, offset = -1, bytes = 0)
|
|||
ngx_open_file_info_t of;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
filename = SvPV_nolen(ST(1));
|
||||
|
||||
|
@ -750,17 +762,18 @@ sendfile(r, filename, offset = -1, bytes = 0)
|
|||
b->file->log = r->connection->log;
|
||||
b->file->directio = of.is_directio;
|
||||
|
||||
(void) ngx_http_perl_output(r, b);
|
||||
(void) ngx_http_perl_output(r, ctx, b);
|
||||
|
||||
|
||||
void
|
||||
flush(r)
|
||||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
ngx_buf_t *b;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
ngx_buf_t *b;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
b = ngx_calloc_buf(r->pool);
|
||||
if (b == NULL) {
|
||||
|
@ -771,7 +784,7 @@ flush(r)
|
|||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->flush");
|
||||
|
||||
(void) ngx_http_perl_output(r, b);
|
||||
(void) ngx_http_perl_output(r, ctx, b);
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
|
||||
|
@ -781,16 +794,14 @@ internal_redirect(r, uri)
|
|||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
SV *uri;
|
||||
ngx_uint_t i;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
uri = ST(1);
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
|
||||
|
||||
if (ngx_http_perl_sv2str(aTHX_ r, &ctx->redirect_uri, uri) != NGX_OK) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
@ -811,9 +822,10 @@ void
|
|||
allow_ranges(r)
|
||||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
r->allow_ranges = 1;
|
||||
|
||||
|
@ -823,13 +835,14 @@ unescape(r, text, type = 0)
|
|||
CODE:
|
||||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
SV *text;
|
||||
int type;
|
||||
u_char *p, *dst, *src;
|
||||
STRLEN len;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
SV *text;
|
||||
int type;
|
||||
u_char *p, *dst, *src;
|
||||
STRLEN len;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
text = ST(1);
|
||||
|
||||
|
@ -858,16 +871,16 @@ variable(r, name, value = NULL)
|
|||
|
||||
dXSTARG;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
SV *name, *value;
|
||||
u_char *p, *lowcase;
|
||||
STRLEN len;
|
||||
ngx_str_t var, val;
|
||||
ngx_uint_t i, hash;
|
||||
ngx_http_perl_var_t *v;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
ngx_http_variable_value_t *vv;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
name = ST(1);
|
||||
|
||||
|
@ -919,8 +932,6 @@ variable(r, name, value = NULL)
|
|||
|
||||
if (vv->not_found) {
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
|
||||
|
||||
if (ctx->variables) {
|
||||
|
||||
v = ctx->variables->elts;
|
||||
|
@ -991,18 +1002,16 @@ sleep(r, sleep, next)
|
|||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
ngx_msec_t sleep;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
ngx_msec_t sleep;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
sleep = (ngx_msec_t) SvIV(ST(1));
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"perl sleep: %M", sleep);
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
|
||||
|
||||
ctx->next = SvRV(ST(2));
|
||||
|
||||
r->connection->write->delayed = 1;
|
||||
|
@ -1016,13 +1025,14 @@ void
|
|||
log_error(r, err, msg)
|
||||
CODE:
|
||||
|
||||
ngx_http_request_t *r;
|
||||
SV *err, *msg;
|
||||
u_char *p;
|
||||
STRLEN len;
|
||||
ngx_err_t e;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_perl_ctx_t *ctx;
|
||||
SV *err, *msg;
|
||||
u_char *p;
|
||||
STRLEN len;
|
||||
ngx_err_t e;
|
||||
|
||||
ngx_http_perl_set_request(r);
|
||||
ngx_http_perl_set_request(r, ctx);
|
||||
|
||||
err = ST(1);
|
||||
|
||||
|
|
|
@ -43,7 +43,8 @@ static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf,
|
|||
static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires,
|
||||
ngx_log_t *log);
|
||||
static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
|
||||
HV *nginx, SV *sub, SV **args, ngx_str_t *handler, ngx_str_t *rv);
|
||||
ngx_http_perl_ctx_t *ctx, HV *nginx, SV *sub, SV **args,
|
||||
ngx_str_t *handler, ngx_str_t *rv);
|
||||
static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);
|
||||
|
||||
static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf);
|
||||
|
@ -199,6 +200,8 @@ ngx_http_perl_handle_request(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
|
||||
|
||||
ctx->request = r;
|
||||
}
|
||||
|
||||
pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
|
||||
|
@ -220,8 +223,8 @@ ngx_http_perl_handle_request(ngx_http_request_t *r)
|
|||
ctx->next = NULL;
|
||||
}
|
||||
|
||||
rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sub, NULL, handler,
|
||||
NULL);
|
||||
rc = ngx_http_perl_call_handler(aTHX_ r, ctx, pmcf->nginx, sub, NULL,
|
||||
handler, NULL);
|
||||
|
||||
}
|
||||
|
||||
|
@ -309,6 +312,8 @@ ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
|||
}
|
||||
|
||||
ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
|
||||
|
||||
ctx->request = r;
|
||||
}
|
||||
|
||||
pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
|
||||
|
@ -321,7 +326,7 @@ ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
|||
PERL_SET_CONTEXT(pmcf->perl);
|
||||
PERL_SET_INTERP(pmcf->perl);
|
||||
|
||||
rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, pv->sub, NULL,
|
||||
rc = ngx_http_perl_call_handler(aTHX_ r, ctx, pmcf->nginx, pv->sub, NULL,
|
||||
&pv->handler, &value);
|
||||
|
||||
}
|
||||
|
@ -372,6 +377,8 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
|
|||
}
|
||||
|
||||
ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
|
||||
|
||||
ctx->request = r;
|
||||
}
|
||||
|
||||
pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
|
||||
|
@ -430,8 +437,8 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
|
|||
asv = NULL;
|
||||
}
|
||||
|
||||
rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv, asv, handler,
|
||||
NULL);
|
||||
rc = ngx_http_perl_call_handler(aTHX_ r, ctx, pmcf->nginx, sv, asv,
|
||||
handler, NULL);
|
||||
|
||||
SvREFCNT_dec(sv);
|
||||
|
||||
|
@ -667,8 +674,9 @@ ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log)
|
|||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub,
|
||||
SV **args, ngx_str_t *handler, ngx_str_t *rv)
|
||||
ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
|
||||
ngx_http_perl_ctx_t *ctx, HV *nginx, SV *sub, SV **args,
|
||||
ngx_str_t *handler, ngx_str_t *rv)
|
||||
{
|
||||
SV *sv;
|
||||
int n, status;
|
||||
|
@ -687,7 +695,7 @@ ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub,
|
|||
|
||||
PUSHMARK(sp);
|
||||
|
||||
sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx));
|
||||
sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(ctx))), nginx));
|
||||
XPUSHs(sv);
|
||||
|
||||
if (args) {
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
typedef ngx_http_request_t *nginx;
|
||||
|
||||
typedef struct {
|
||||
ngx_http_request_t *request;
|
||||
|
||||
ngx_str_t filename;
|
||||
ngx_str_t redirect_uri;
|
||||
ngx_str_t redirect_args;
|
||||
|
|
Loading…
Reference in a new issue