Subject: Re: [RFC PATCHv2 04/10] gitweb: Use Cache::Cache compatibile (get, set) output caching

From: Jakub Narebski <[email-masked]>
Date: Wed, 10 Feb 2010 02:12:24 +0100

On Tue, 9 Feb 2010 at 11:30 +0100, Jakub Narebski wrote:

> The cache_fetch subroutine captures output (from STDOUT only, as
> STDERR is usually logged) using either ->push_layer()/->pop_layer()
> from PerlIO::Util submodule (if it is available), or by setting and
> restoring *STDOUT.  Note that only the former could be tested reliably
> to be reliable in t9503 test!

Scratch that, I have just checked that (at least for Apache + mod_cgi,
but I don't think that it matters) the latter solution, with setting
and restoring *STDOUT doesn't work: I would get data in cache (so it
can be restored later), but instead of output I would get Internal Server
Error ("The server encountered an internal error or misconfiguration and
was unable to complete your request.") without even a hint what the
problem was.  Sprinkling "die ...: $!" didn't help to catch this error:
I suspect that the problem is with capturing.

So we either would have to live with non-core PerlIO::Util or (pure Perl)
Capture::Tiny, or do the 'print -> print $out' patch...

[....]
> Capturing gitweb output
> =======================
> When output (response) caching is enabled, the caching mechanism has to
> capture gitweb output (perhaps while printing it to standard output) to
> save it to cache, unless the data is available in cache and not expired.
> 
> Because die_error uses 'exit', and because it uses git_header_html and
> other printing subroutines (which output has to be captured in other
> situations), it needs to disable caching, unless we are "tee"-ing.
> Otherwise we would get no output from die_error (because it is captured),
> but also we would not get data to be saved in cache and printed, because
> 'exit' in die_error would exit capture, too.  This restricts methods and
> modules that can be used to capture output.
> 
> Below there are presented various considered and used ways of capturing the
> output, or "tee"-ing it (capturing while printing), with their advantages
> and disadvantages.
> 
> 
> Capturing output (capture)
> ~~~~~~~~~~~~~~~~~~~~~~~~~~
[...]

> 5. Without 'print <sth>' to 'print $out <sth>' change to gitweb, one can try
>    manipulating *STDOUT directly, first saving *STDOUT or \*STDOUT to some
>    variable, then setting *STDOUT = $data_fh, where $data_fh is filehandle
>    opened to in-memory file.
> 
>    This seems to work, does not require large patch to gitweb, and does not
>    require extra (non-core) Perl module.  Nevertheless it seems fragile with
>    respect to restoring STDOUT, and even though basic tests (not included)
>    of this mechanism producted expected result, I wasn't able to write
>    working tests when using this method.
> 
>    We could probably examine how Capture::Tiny does it, and reuse (copy)
>    relevant parts of code, perhaps duplicating STDOUT, closing it and then
>    reopening as in-memory filehandle.
> 
>    YMMV (Your Mileage May Vary).

-- 
Jakub Narebski
Poland