On Wed, Sep 10, 2008 at 6:59 PM, Sergio Salvi <[EMAIL PROTECTED]> wrote: > There is a race condition in C::P::Session when using > C::Engine::Apache (and probably other engines too): > > I have a simple controller action (let's call it /save) that gets data > submitted from an HTML form via POST, process that request, stores > some stuff in the session and flash and then redirects with HTTP 303 > to another action (/display). > > The /display action then displays the regular "submit successful" > message that was set on the previous action by using $c->flash. The > problem is that the browser is GETting /display before /save is > finished storing the session and flash rows in the database. Then, of > course, /display thinks nothing has happened and doesn't display the > data from flash. > > After a bunch of debugging and stack traces :), I figured out the > problem is that C::P::Session's finalize() calls $c->NEXT::finalize() > before calling $c->finalize_session, so > C::Engine::Apache->finalize_body() gets executed *before* the session > is flushed in the database, making the browser access /display even > though the session may not be stored yet: > > # From C::P::Session: > > sub finalize { > my $c = shift; > my $ret = $c->NEXT::finalize(@_); > > # then finish the rest > $c->finalize_session; > return $ret; > } > > I've solved this problem by extending C::P::Session and changing the > behaviour of finalize(), like this: > > ### > > package Catalyst::Plugin::MySession; > use base qw/Catalyst::Plugin::Session/; > > use strict; > use warnings; > > sub finalize { > my $c = shift; > $c->finalize_session; > my $ret = $c->NEXT::finalize(@_); > return $ret; > } > > 1; > ### > > But I realize this may create problems later on if other plugins have > finalize() that modify stuff in the session or flash, because then it > would be too late to modify it as the session/flash was already > stored. > > How can I tell Catalyst to call the Engine's finalize() method *last*, > after every other finalize() has been called? > > I think that would be the safest way to fix this problem. It is > probably related to C3 MRO, but I'm not sure how to approach this > within Catalyst. > > Thank you! > Sergio Salvi > > PS: My environment is: > > Debian 4.0, stock perl 5.8.8, Apache 2.2.3 with mod_perl 2.0.2 > (prefork, no reverse proxy at this moment), MySQL 5.0.32 with InnoDB > and the latest version of major Perl modules: > > Catalyst 5.7.014 > C::P::Session 0.19 > C::P::Session::Store::DBIC 0.06 >
Bump :) All I'd like to know is this: How can I tell Catalyst to call the Engine's finalize() method *last*, after every other finalize() has been called? Thanks, Sergio _______________________________________________ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/