Perl: creating input and error streams if closed.

Application handler can do anything with a stream object (including close it).
Once the stream is closed, Unit creates a new stream.

This closes #616 issue on GitHub.
This commit is contained in:
Max Romanov
2021-12-27 16:37:35 +03:00
parent 6507849282
commit f845283820
7 changed files with 167 additions and 168 deletions

View File

@@ -28,19 +28,15 @@ typedef struct {
} nxt_perl_psgi_ctx_t;
static long nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl,
static SSize_t nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length);
static long nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl,
static SSize_t nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length);
static long nxt_perl_psgi_io_input_flush(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg);
static long nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl,
static SSize_t nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length);
static long nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl,
static SSize_t nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length);
static long nxt_perl_psgi_io_error_flush(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg);
/*
static void nxt_perl_psgi_xs_core_global_changes(PerlInterpreter *my_perl,
@@ -57,10 +53,8 @@ static SV *nxt_perl_psgi_call_method(PerlInterpreter *my_perl, SV *obj,
/* For currect load XS modules */
EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
static nxt_int_t nxt_perl_psgi_io_input_init(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg);
static nxt_int_t nxt_perl_psgi_io_error_init(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg);
static int nxt_perl_psgi_io_init(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, const char *mode, void *req);
static int nxt_perl_psgi_ctx_init(const char *script,
nxt_perl_psgi_ctx_t *pctx);
@@ -125,20 +119,26 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
nxt_perl_psgi_start,
};
const nxt_perl_psgi_io_tab_t nxt_perl_psgi_io_tab_input = {
.read = nxt_perl_psgi_io_input_read,
.write = nxt_perl_psgi_io_input_write,
};
static long
const nxt_perl_psgi_io_tab_t nxt_perl_psgi_io_tab_error = {
.read = nxt_perl_psgi_io_error_read,
.write = nxt_perl_psgi_io_error_write,
};
static SSize_t
nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length)
{
nxt_perl_psgi_ctx_t *pctx;
pctx = arg->pctx;
return nxt_unit_request_read(pctx->req, vbuf, length);
return nxt_unit_request_read(arg->req, vbuf, length);
}
static long
static SSize_t
nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length)
{
@@ -146,15 +146,7 @@ nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl,
}
static long
nxt_perl_psgi_io_input_flush(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg)
{
return 0;
}
static long
static SSize_t
nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length)
{
@@ -162,25 +154,13 @@ nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl,
}
static long
static SSize_t
nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length)
{
nxt_perl_psgi_ctx_t *pctx;
nxt_unit_req_error(arg->req, "Perl: %s", (const char*) vbuf);
pctx = arg->pctx;
nxt_unit_req_error(pctx->req, "Perl: %s", (const char*) vbuf);
return (long) length;
}
static long
nxt_perl_psgi_io_error_flush(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg)
{
return 0;
return (SSize_t) length;
}
@@ -461,70 +441,49 @@ nxt_perl_psgi_module_create(const char *script)
}
static nxt_int_t
nxt_perl_psgi_io_input_init(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg)
static int
nxt_perl_psgi_io_init(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg, const char *mode, void *req)
{
SV *io;
PerlIO *fp;
fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg, "r");
if (arg->io == NULL) {
fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg->rv, mode);
if (nxt_slow_path(fp == NULL)) {
return NXT_UNIT_ERROR;
}
if (nxt_slow_path(fp == NULL)) {
return NXT_ERROR;
io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp);
if (nxt_slow_path(io == NULL)) {
nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp);
return NXT_UNIT_ERROR;
}
arg->io = io;
arg->fp = fp;
}
io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp);
arg->req = req;
if (nxt_slow_path(io == NULL)) {
nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp);
return NXT_ERROR;
}
arg->io = io;
arg->fp = fp;
arg->flush = nxt_perl_psgi_io_input_flush;
arg->read = nxt_perl_psgi_io_input_read;
arg->write = nxt_perl_psgi_io_input_write;
return NXT_OK;
return NXT_UNIT_OK;
}
static nxt_int_t
nxt_perl_psgi_io_error_init(PerlInterpreter *my_perl,
nxt_perl_psgi_io_arg_t *arg)
static void
nxt_perl_psgi_io_release(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg)
{
SV *io;
PerlIO *fp;
fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg, "w");
if (nxt_slow_path(fp == NULL)) {
return NXT_ERROR;
if (arg->io != NULL) {
SvREFCNT_dec(arg->io);
arg->io = NULL;
}
io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp);
if (nxt_slow_path(io == NULL)) {
nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp);
return NXT_ERROR;
}
arg->io = io;
arg->fp = fp;
arg->flush = nxt_perl_psgi_io_error_flush;
arg->read = nxt_perl_psgi_io_error_read;
arg->write = nxt_perl_psgi_io_error_write;
return NXT_OK;
}
static int
nxt_perl_psgi_ctx_init(const char *script, nxt_perl_psgi_ctx_t *pctx)
{
int status;
int status, res;
char *run_module;
PerlInterpreter *my_perl;
@@ -577,19 +536,27 @@ nxt_perl_psgi_ctx_init(const char *script, nxt_perl_psgi_ctx_t *pctx)
goto fail;
}
pctx->arg_input.pctx = pctx;
pctx->arg_input.rv = newSV_type(SVt_RV);
sv_setptrref(pctx->arg_input.rv, &pctx->arg_input);
SvSETMAGIC(pctx->arg_input.rv);
status = nxt_perl_psgi_io_input_init(my_perl, &pctx->arg_input);
if (nxt_slow_path(status != NXT_OK)) {
pctx->arg_input.io_tab = &nxt_perl_psgi_io_tab_input;
res = nxt_perl_psgi_io_init(my_perl, &pctx->arg_input, "r", NULL);
if (nxt_slow_path(res != NXT_UNIT_OK)) {
nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.input");
goto fail;
}
pctx->arg_error.pctx = pctx;
pctx->arg_error.rv = newSV_type(SVt_RV);
sv_setptrref(pctx->arg_error.rv, &pctx->arg_error);
SvSETMAGIC(pctx->arg_error.rv);
status = nxt_perl_psgi_io_error_init(my_perl, &pctx->arg_error);
if (nxt_slow_path(status != NXT_OK)) {
nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.errors");
pctx->arg_error.io_tab = &nxt_perl_psgi_io_tab_error;
res = nxt_perl_psgi_io_init(my_perl, &pctx->arg_error, "w", NULL);
if (nxt_slow_path(res != NXT_UNIT_OK)) {
nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.error");
goto fail;
}
@@ -607,6 +574,9 @@ nxt_perl_psgi_ctx_init(const char *script, nxt_perl_psgi_ctx_t *pctx)
fail:
nxt_perl_psgi_io_release(my_perl, &pctx->arg_input);
nxt_perl_psgi_io_release(my_perl, &pctx->arg_error);
if (run_module != NULL) {
nxt_unit_free(NULL, run_module);
}
@@ -614,6 +584,8 @@ fail:
perl_destruct(my_perl);
perl_free(my_perl);
pctx->my_perl = NULL;
return NXT_UNIT_ERROR;
}
@@ -672,21 +644,25 @@ nxt_perl_psgi_env_create(PerlInterpreter *my_perl,
r->tls ? newSVpv("https", 5)
: newSVpv("http", 4)));
RC(nxt_perl_psgi_io_init(my_perl, &pctx->arg_input, "r", req));
RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.input"),
SvREFCNT_inc(pctx->arg_input.io)));
SvREFCNT_inc(pctx->arg_input.io)));
RC(nxt_perl_psgi_io_init(my_perl, &pctx->arg_error, "w", req));
RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.errors"),
SvREFCNT_inc(pctx->arg_error.io)));
SvREFCNT_inc(pctx->arg_error.io)));
RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.multithread"),
nxt_perl_psgi_ctxs != NULL
? &PL_sv_yes : &PL_sv_no));
nxt_perl_psgi_ctxs != NULL
? &PL_sv_yes : &PL_sv_no));
RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.multiprocess"),
&PL_sv_yes));
&PL_sv_yes));
RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.run_once"),
&PL_sv_no));
&PL_sv_no));
RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.nonblocking"),
&PL_sv_no));
&PL_sv_no));
RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.streaming"),
&PL_sv_yes));
&PL_sv_yes));
RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("QUERY_STRING"),
&r->query, r->query_length));
@@ -1447,11 +1423,11 @@ nxt_perl_psgi_ctx_free(nxt_perl_psgi_ctx_t *pctx)
PERL_SET_CONTEXT(my_perl);
nxt_perl_psgi_layer_stream_io_destroy(aTHX_ pctx->arg_input.io);
nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ pctx->arg_input.fp);
SvREFCNT_dec(pctx->arg_input.rv);
SvREFCNT_dec(pctx->arg_error.rv);
nxt_perl_psgi_layer_stream_io_destroy(aTHX_ pctx->arg_error.io);
nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ pctx->arg_error.fp);
nxt_perl_psgi_io_release(my_perl, &pctx->arg_input);
nxt_perl_psgi_io_release(my_perl, &pctx->arg_error);
perl_destruct(my_perl);
perl_free(my_perl);