Dept. of Mason Subrequest Bug Fixes

This post is HARD geeky, but I’m putting it out there for Googlejuice reasons.

Recently, some code over at Spacetaker stopped working, and I couldn’t figure out why. The salient bit of code is this:

  my $req = $m->make_subrequest( comp => '/httpdocs/newsletter.html',
                                 args => [ id => $ff->{id}, fridayfotoflag => 't' ],
                                 out_method => \$newsletter,
                                 autoflush => 0 );

  $req->exec;

  my $mail = MIME::Lite->new( From => $sender,
                              To => $where{$ARGS{do}},
                              Subject => "FridayFoto for $ff->{week}",
                              Type => "text/html",
                              Data => $newsletter);

  $mail->send('smtp', $server, Timeout => 60, Debut => 1);
  
  $m->out(qq{Success!
      Newsletter "$ff->{title}" for the week of $ff->{week} has 
      been sent to $where{$ARGS{do}}.);

Ideally, this assembles the newsletter itself with the $m->make_subrequest call, and then mails it with the calls to MIME::Lite to whomever it appropriate. It then went on to display a success message noting to whom the the mail (a weekly newsletter) had been sent. All good, right?

Well, no. All of a sudden (see below), the page in question would churn and churn and churn, but never actually load. The problem was clearly NOT the MIME::Lite calls, as (a) they continued to do their job even as the page churned and (b) the page churned endlessly even with those lines commented out. Under no circumstances did the text in the $m->out call get shown, but debugging output to STDERR would show up pretty much all the way through.

I consulted my MasonGuru for help, and we finally sat down to chase it this morning. Step one was upgrading Mason; I was a version or so behind. After upgrading from 1.28 to 1.3101, we started getting errors instead of silent failures, which is definitely a step in the right direction. Turns out, the subrequest call was failing (silently under 1.28, but with an error under 1.3101) for no apparent reason. Much Googling finally pointed out the issue, which we found referenced here and detailed here. For posterity, I’ll reproduce it:

There is a known problem in MasonX::Request::WithApacheSession 0.30, which is the most current release. Subrequests may work once, but after that they fail in a sort of endless loop condition for reasons I don’t understand.

To make this work, do this:

From: Derek Poon  OCF.Berkeley.EDU>
Subject: MasonX::Request::WithApacheSession 0.30 bug: subrequests
Newsgroups: gmane.comp.web.mason.devel
Date: 2005-07-10 02:03:23 GMT (12 weeks, 3 days, 12 hours and 14 minutes ago)

Hi,

There is a bug in MasonX::Request::WithApacheSession 0.30 that causes  
an error when executing subrequests.

I have this in my httpd.conf:

PerlSetVar MasonRequestClass MasonX::Request::WithApacheSession

When running  $m->subexec(...)  in Mason, I get this error in the  
browser:

error:
Can't call method "exec" on an undefined value at [...]/HTML/Mason/ 
Request.pm line 538,  line 2.

Trace begun at [...]/HTML/Mason/Exceptions.pm line 128
HTML::Mason::Exceptions::rethrow_exception('Can\'t call method "exec"  
on an undefined value at [...]/HTML/Mason/Request.pm line 538,   
line 2.^J') called at [...]/HTML/Mason/Request.pm line 538
HTML::Mason::Request::subexec([...]) called at [...]/autohandler line 58
[...]

Here's the fix:

--- MasonX-Request-WithApacheSession-0.30/lib/MasonX/Request/ 
WithApacheSession.pm.subrequest    2004-03-19 23:27:55.000000000 +0100
+++ MasonX-Request-WithApacheSession-0.30/lib/MasonX/Request/ 
WithApacheSession.pm       2005-07-10 03:52:35.000000000 +0200
     -74,7 +74,7     
      my $self = $class->SUPER::new(  _);
-    return if $self->is_subrequest;
+    return $self if $self->is_subrequest;
      # backwards compatibility
      $self->{session_param_name} =

For the unitiated, this means:

  1. Find the Perl module named WithApacheSession.pm, which will be in a directory called MasonX/Request/ that is contained in one of the directories listed when you do a perl -V from your server’s command line. On my OS X server, it’s
    /Library/Perl/5.8.1/MasonX/Request/WithApacheSession.pm
  2. Locate the line “return if $self->is_subrequest;“, which should be around/about 74.
  3. Change it to “return $self if $self->is_subrequest;
  4. Stop and Start Apache (not a restart; do a full stop and start).
  5. Bob’s your uncle.

The reason this mysteriously started breaking was that I installed the module in question to support sessions, and it steps in to handle all subrequests, causing the problem to occur in non-session-related code.

Comments are closed.