You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl-cvs@perl.apache.org by st...@apache.org on 2003/01/14 07:42:44 UTC

cvs commit: modperl-2.0/t/response/TestError push_handlers.pm

stas        2003/01/13 22:42:44

  Modified:    src/modules/perl modperl_callback.c
               .        Changes
  Added:       t/error  push_handlers.t
               t/response/TestError push_handlers.pm
  Log:
  prevent a segfault when push_handlers are used to push a handler into
  the currently phase and switching the handler (perl-script/modperl) +
  tests
  
  Revision  Changes    Path
  1.52      +8 -4      modperl-2.0/src/modules/perl/modperl_callback.c
  
  Index: modperl_callback.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_callback.c,v
  retrieving revision 1.51
  retrieving revision 1.52
  diff -u -r1.51 -r1.52
  --- modperl_callback.c	1 Jan 2003 03:45:54 -0000	1.51
  +++ modperl_callback.c	14 Jan 2003 06:42:43 -0000	1.52
  @@ -93,7 +93,7 @@
       modperl_handler_t **handlers;
       apr_pool_t *p = NULL;
       MpAV *av, **avp;
  -    int i, status = OK;
  +    int i, nelts, status = OK;
       const char *desc = NULL;
       AV *av_args = Nullav;
   
  @@ -173,11 +173,15 @@
       };
   
       /* XXX: deal with {push,set}_handler of the phase we're currently in */
  -    MP_TRACE_h(MP_FUNC, "running %d %s handlers\n",
  -               av->nelts, desc);
  +    /* for now avoid the segfault by not letting av->nelts grow if
  +     * somebody push_handlers to the phase we are currently in, but
  +     * different handler e.g. jumping from 'modperl' to 'perl-script',
  +     * before calling push_handler */
  +    nelts = av->nelts;
  +    MP_TRACE_h(MP_FUNC, "running %d %s handlers\n", nelts, desc);
       handlers = (modperl_handler_t **)av->elts;
   
  -    for (i=0; i<av->nelts; i++) {
  +    for (i=0; i<nelts; i++) {
           if ((status = modperl_callback(aTHX_ handlers[i], p, r, s, av_args)) != OK) {
               status = modperl_errsv(aTHX_ status, r, s);
           }
  
  
  
  1.100     +4 -0      modperl-2.0/Changes
  
  Index: Changes
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/Changes,v
  retrieving revision 1.99
  retrieving revision 1.100
  diff -u -r1.99 -r1.100
  --- Changes	12 Jan 2003 04:05:48 -0000	1.99
  +++ Changes	14 Jan 2003 06:42:44 -0000	1.100
  @@ -10,6 +10,10 @@
   
   =item 1.99_09-dev
   
  +prevent a segfault when push_handlers are used to push a handler into
  +the currently phase and switching the handler (perl-script/modperl)
  +[Stas]
  +
   Add $filter->seen_eos to the streaming filter api to know when eos has
   been seen, so special signatures can be passed and any data stored in
   the context flushed + tests. [Stas]
  
  
  
  1.1                  modperl-2.0/t/error/push_handlers.t
  
  Index: push_handlers.t
  ===================================================================
  use strict;
  use warnings FATAL => 'all';
  
  use Apache::Test;
  use Apache::TestUtil;
  use Apache::TestRequest;
  
  plan tests => 1;
  
  my $location = "/TestError::push_handlers";
  my $expected = "ok";
  my $received = GET_BODY $location;
  
  ok t_cmp($expected, $received);
  
  
  
  1.1                  modperl-2.0/t/response/TestError/push_handlers.pm
  
  Index: push_handlers.pm
  ===================================================================
  package TestError::push_handlers;
  
  # This test verifies that we don't segfault when push_handlers are
  # used incorrectly. Here the handler() is running under 
  #   SetHandler modperl
  # and it modifies its handler to be 'perl-script', plus pushes another
  # handler to run. The result is that the first time handler() is run
  # under the 'modperl' handler it returns declined, therefore Apache
  # runs the registered 'perl-script' handler (which handler() has
  # pushed in plus itself. So the handler() is executed again, followed
  # by real_response(). Notice that it pushes yet another real_response
  # callback onto the list of handlers. 
  #
  # suprisingly the response eventually works, but this is a wrong way
  # to accomplish that thing. And one of the earlier stages should be
  # used to push handlers. 
  #
  # Don't modify the handler (modperl|perl-script) during the response
  # handler run-time, because if OK is not returned, the handler will be
  # executed again.
  
  
  use strict;
  use warnings;# FATAL => 'all';
  
  use Apache::RequestRec ();
  use Apache::RequestIO ();
  use Apache::RequestUtil ();
  
  use Apache::Const -compile => qw(OK DECLINED);
  
  sub handler {
      my $r = shift;
  
      #warn "handler called\n";
  
      $r->handler("perl-script");
      $r->push_handlers(PerlResponseHandler => \&real_response);
  
      return Apache::DECLINED;
  }
  
  sub real_response {
      my $r = shift;
  
      #warn "real_response called\n";
  
      $r->content_type('text/plain');
      $r->print('ok');
  
      return Apache::OK;
  }
  
  1;
  __END__