On Tuesday 30 March 2010 20:08:00 Fred Moyer wrote:
> Torsten can you post a breakdown of each part in the patch so those of
> us who can't grok all of it (I'm one of them!) can get a handle (no
> pun intended) on what each part does?
>
Best I think if you look at the patch result. Previously there were 2
very similar sets of functions modperl_io_perlio_{override,restore}_std{in,out}
and a XXX-comment suggesting merging of these 2 sets. Now, there is
one override-function and one restorer.
I use the SV slot of the GV to remember the open string to be used by the
restorer. Now, I think I could avoid that and use Perl_form + fileno in the
restorer. But the SV slot can be used for example to store $|-ness of the
handle. This would eliminate the other XXX-comment.
Much more interesting for me is is the IO-redirecting stuff correct? And
related,
in which cases do IFP and OFP of a handle differ or do they differ or rather in
which cases do fileno(IFP) differ from fileno(OFP)?
static GV *modperl_io_perlio_override_stdhandle(pTHX_ request_rec *r, int mode)
{
dHANDLE(mode == O_RDONLY ? "STDIN" : "STDOUT");
int status, fileno;
GV *handle_save = (GV*)Nullsv;
SV *sv = sv_newmortal();
SV *gsv;
IO *io;
MP_TRACE_o(MP_FUNC, "start STD%s", mode == O_RDONLY ? "IN" : "OUT");
/* if STDIN is open, dup it, to be restored at the end of response */
if (handle && SvTYPE(handle) == SVt_PVGV &&
IoTYPE(io=GvIO(handle)) != IoTYPE_CLOSED &&
(fileno=PerlIO_fileno(IoIFP(io))) >= 0) {
handle_save = gv_fetchpv(Perl_form(aTHX_
"Apache2::RequestIO::_GEN_%ld",
(long)PL_gensym++),
GV_ADD, SVt_PVIO);
if (!GvSV(handle_save)) GvSV(handle_save) = newSV(0);
gsv=GvSV(handle_save);
/* open my $oldout, "<&=".fileno(STDIN) or die "Can't dup STDIN: $!"; */
SvUPGRADE(gsv, SVt_PV);
SvGROW(gsv, 20);
sv_setpvf(gsv, mode == O_RDONLY ? "<&=%d" : ">&=%d", fileno);
status = do_open(handle_save, SvPVX(GvSV(handle_save)),
SvCUR(GvSV(handle_save)), FALSE, mode, 0, Nullfp);
if (status == 0) {
Perl_croak(aTHX_ "Failed to dup STD%s: %" SVf,
mode == O_RDONLY ? "IN" : "OUT", get_sv("!", TRUE));
}
/* similar to PerlIO::scalar, the PerlIO::Apache layer doesn't
* have file descriptors, so STDIN must be closed before it can
* be reopened */
do_close(handle, TRUE);
}
sv_setref_pv(sv, "Apache2::RequestRec", (void*)r);
status = do_open9(handle, mode == O_RDONLY ? "<:Apache2" : ">:Apache2",
9, FALSE, mode, 0, Nullfp, sv, 1);
if (status == 0) {
Perl_croak(aTHX_ "Failed to open STD%s: %" SVf,
mode == O_RDONLY ? "IN" : "OUT", get_sv("!", TRUE));
}
if (mode == O_WRONLY) {
/* XXX: shouldn't we preserve the value STDOUT had before it was
* overridden? */
IoFLUSH_off(handle); /* STDOUT's $|=0 */
}
MP_TRACE_o(MP_FUNC, "end STD%s", mode==O_RDONLY ? "IN" : "OUT");
return handle_save;
}
MP_INLINE GV *modperl_io_perlio_override_stdin(pTHX_ request_rec *r)
{
return modperl_io_perlio_override_stdhandle(aTHX_ r, O_RDONLY);
}
/* XXX: refactor to merge with the previous function */
MP_INLINE GV *modperl_io_perlio_override_stdout(pTHX_ request_rec *r)
{
return modperl_io_perlio_override_stdhandle(aTHX_ r, O_WRONLY);
}
static void modperl_io_perlio_restore_stdhandle(pTHX_ GV *handle, int mode)
{
GV *handle_orig = gv_fetchpv(mode == O_RDONLY ? "STDIN" : "STDOUT",
FALSE, SVt_PVIO);
MP_TRACE_o(MP_FUNC, "start STD%s", mode == O_RDONLY ? "IN" : "OUT");
/* since closing unflushed STDOUT may trigger a subrequest
* (e.g. via mod_include), resulting in potential another response
* handler call, which may try to close STDOUT too. We will
* segfault, if that subrequest doesn't return before the the top
* level STDOUT is attempted to be closed. To prevent this
* situation always explicitly flush STDOUT, before reopening it.
*/
if (mode == O_WRONLY &&
GvIOn(handle_orig) && IoOFP(GvIOn(handle_orig)) &&
(PerlIO_flush(IoOFP(GvIOn(handle_orig))) == -1)) {
Perl_croak(aTHX_ "Failed to flush STDOUT: %" SVf, get_sv("!", TRUE));
}
/* close the overriding filehandle */
do_close(handle_orig, FALSE);
/*
* open STDIN, "<&=$FD_SAVED" or die "Can't dup STDIN_SAVED: $!";
*/
if (handle != (GV*)Nullsv) {
SV *err = Nullsv;
MP_TRACE_o(MP_FUNC, "restoring STD%s", mode == O_RDONLY ? "IN" : "OUT");
if (do_open(handle_orig, SvPVX(GvSV(handle)), SvCUR(GvSV(handle)),
FALSE, mode, 0, NULL) == 0) {
err = get_sv("!", TRUE);
}
do_close(handle, FALSE);
(void)hv_delete(gv_stashpv("Apache2::RequestIO", TRUE),
GvNAME(handle), GvNAMELEN(handle), G_DISCARD);
if (err != Nullsv) {
Perl_croak(aTHX_ "Failed to restore STD: %" SVf,
mode == O_RDONLY ? "IN" : "OUT", err);
}
}
MP_TRACE_o(MP_FUNC, "end STD%s", mode == O_RDONLY ? "IN" : "OUT");
}
MP_INLINE void modperl_io_perlio_restore_stdin(pTHX_ GV *handle)
{
modperl_io_perlio_restore_stdhandle(aTHX_ handle, O_RDONLY);
}
MP_INLINE void modperl_io_perlio_restore_stdout(pTHX_ GV *handle)
{
modperl_io_perlio_restore_stdhandle(aTHX_ handle, O_WRONLY);
}
Torsten Förtsch
--
Need professional modperl support? Hire me! (http://foertsch.name)
Like fantasy? http://kabatinte.net
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]