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: dev-unsubscr...@perl.apache.org For additional commands, e-mail: dev-h...@perl.apache.org