stas        2003/11/22 02:27:42

  Modified:    src/modules/perl modperl_io.c
               .        Changes
  Added:       t/modules include_subreq.t
               t/response/TestModules include_subreq.pm
  Log:
  Fix :Apache perlio's STDOUT to be reentrant + modules/include_subreq
  test
  
  Revision  Changes    Path
  1.20      +11 -2     modperl-2.0/src/modules/perl/modperl_io.c
  
  Index: modperl_io.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_io.c,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -u -r1.19 -r1.20
  --- modperl_io.c      15 Oct 2003 00:37:59 -0000      1.19
  +++ modperl_io.c      22 Nov 2003 10:27:41 -0000      1.20
  @@ -190,9 +190,18 @@
   
       MP_TRACE_o(MP_FUNC, "start");
   
  -    /* Perl_do_close(aTHX_ handle_orig, FALSE); */
  -
  +    /* 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 (GvIOn(handle_orig) && IoOFP(GvIOn(handle_orig))) {
  +        Perl_PerlIO_flush(aTHX_ IoOFP(GvIOn(handle_orig)));
  +    }
       /* open STDOUT, ">&STDOUT_SAVED" or die "Can't dup STDOUT_SAVED: $!"; */
  +    /* open first closes STDOUT */
       status = Perl_do_open9(aTHX_ handle_orig, ">&", 2, FALSE, O_WRONLY,
                              0, Nullfp, (SV*)handle, 1);
       Perl_do_close(aTHX_ handle, FALSE);
  
  
  
  1.1                  modperl-2.0/t/modules/include_subreq.t
  
  Index: include_subreq.t
  ===================================================================
  use strict;
  use warnings FATAL => 'all';
  
  use Apache::Test;
  use Apache::TestRequest;
  use Apache::TestUtil;
  
  my $module = 'TestModules::include_subreq';
  my $location = '/' . Apache::TestRequest::module2path($module);
  
  plan tests => 1, ['include'];
  
  my($res, $str);
  
  my $expected = "subreq is quite ok";
  my $received = GET_BODY_ASSERT "$location/one";
  ok t_cmp($expected, $received, "handler => filter => handler");
  
  
  
  
  1.1                  modperl-2.0/t/response/TestModules/include_subreq.pm
  
  Index: include_subreq.pm
  ===================================================================
  package TestModules::include_subreq;
  
  # this test calls a simple response handler, whose output includes a
  # simple SSI directive, processed by the INCLUDES output filter, which
  # triggers another response handler, which again returns an SSI
  # directive, again processed by INCLUDES, which again calls a response
  # handler
  #
  # main
  # resp => INCLUDES =>                                        => client
  #                  => 1st                                  =>
  #                     subreq => INCLUDES =>              =>
  #                     response           =>            =>
  #                                        => 2nd      =>
  #                                           subreq =>
  #                                           response
  #
  #
  #
  # here we test whether :Apache perlio (STDOUT) is reentrant, since the test
  # overrides STDOUT 3 times, recursively.
  
  use strict;
  use warnings FATAL => 'all';
  
  use Apache::TestTrace;
  
  use Apache::Const -compile => 'OK';
  
  sub handler {
      my $r = shift;
  
      $r->content_type('text/plain');
  
      my $path_info = $r->path_info || '';
      my $uri = $r->uri;
  
      debug "uri: $uri, path_info: $path_info";
  
      if ($path_info eq '/one') {
          $uri =~ s/one/two/;
          print qq[subreq <!--#include virtual="$uri" -->ok];
      }
      elsif ($path_info eq '/two') {
          $uri = "/TestModules__include_subreq_dup/three";
          #$uri =~ s/two/three/;
          print qq[is <!--#include virtual="$uri" -->];
          #print "is";
      }
      elsif ($path_info eq '/three') {
          print "quite ";
      }
      else {
          die "something is wrong, didn't get path_info";
      }
  
      Apache::OK;
  }
  
  1;
  __END__
  # notice that perl-script is used on purpose here - testing whether
  # :Apache perlio is reentrant (SetHandler modperl doesn't go through
  # :Apache perlio layer)
  SetHandler perl-script
  PerlSetOutputFilter INCLUDES
  Options +IncludesNoExec
  <Base>
  # it's silly that we have to duplicate the resource, but mod_include
  # otherwise thinks we have a recursive call loop
  <Location /TestModules__include_subreq_dup>
      PerlSetOutputFilter INCLUDES
      Options +IncludesNoExec
      SetHandler perl-script
      PerlResponseHandler TestModules::include_subreq
  </Location>
  </Base>
  
  
  
  1.259     +3 -0      modperl-2.0/Changes
  
  Index: Changes
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/Changes,v
  retrieving revision 1.258
  retrieving revision 1.259
  diff -u -u -r1.258 -r1.259
  --- Changes   22 Nov 2003 08:26:00 -0000      1.258
  +++ Changes   22 Nov 2003 10:27:42 -0000      1.259
  @@ -12,6 +12,9 @@
   
   =item 1.99_12-dev
   
  +Fix :Apache perlio's STDOUT to be reentrant + modules/include_subreq
  +test [Stas]
  +
   fix slurp_filename to always open the file and not try to guess
   whether filename has been already opened, as there is no reliable way
   to accomplish that [Stas]
  
  
  

Reply via email to