You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Todd Finney <tf...@boygenius.com> on 2007/01/30 22:47:58 UTC
Apache::Session::MySQL, light/heavy proxy, wedging
I'm having a problem with Apache::Session::MySQL and mod_proxy, and I can't
seem to wrap my head around what's going on.
I have two servers running in the light/heavy configuration as outlined in
the guide. Both servers are 1.3.34. On the lightweight server, my proxy
section looks like this:
----
RewriteEngine on
RewriteRule ^/images - [L]
RewriteRule .(css|ico)$ - [L]
RewriteRule .swf$ - [L]
RewriteRule ^.(.*) http://192.168.0.4:8080/$1 [P]
----
On the heavy server, I'm running ePerl with a PerlHeaderParserHandler that
is essentially just a wrapper for Apache::Session::MySQL
----
PerlHeaderParserHandler BoyGenius::AccessManagement::SessionTestTwo
<FilesMatch "\.phtml$">
SetHandler perl-script
PerlHandler Apache::ePerl
</FilesMatch>
-----
I have a big complicated handler that does all kinds of fancy crap, but in
the interest of nailing down the problem I've replaced it with one that was
pretty much cut and pasted from the Apache::Session perldoc:
----
package BoyGenius::AccessManagement::SessionTestTwo;
use Apache::Session::MySQL;
use Apache;
use strict;
sub handler {
my $r = shift;
#read in the cookie if this is an old session
my $cookie = $r->header_in('Cookie');
$cookie =~ s/SESSION_ID=(\w*)/$1/;
#create a session object based on the cookie we got from the browser,
#or a new session if we got no cookie
my %session;
tie %session, 'Apache::Session::MySQL', $cookie, {
DataSource => 'dbi:mysql:boygenius', #these arguments are
UserName => 'nobody', #required when using
Password => 'XXXXXXXXX', #MySQL.pm
LockDataSource => 'dbi:mysql:boygenius',
LockUserName => 'nobody',
LockPassword => 'XXXXXXXXX'
};
$r->pnotes('SESSION_ID', $session{_session_id});
#Might be a new session, so lets give them their cookie back
my $session_cookie = "SESSION_ID=$session{_session_id};";
$r->header_out("Set-Cookie" => $session_cookie);
}
1;
----
The problem I'm having is with this line:
$r->pnotes('SESSION_ID', $session{_session_id});
When this line is in there, I see the following behavior:
- When I fire up a new browser and access http://192.168.0.4/, the browser
hangs. In my bigger fancier handler with more detailed logging, it seems
to hang right before the session tie.
- When I fire up a new browser and access http://192.168.0.4/index.phtml,
the page comes up as it should.
- When I fire up a new browser and access http://192.168.0.4:8080/, the
page comes up as it should.
- When I fire up a new browser and access either
http://192.168.0.4/index.phtml or http://192.168.0.4:8080/, and then access
http://192.169.0.4/, the page comes up fine.
- When I fire up a new browser and access http://192.168.0.4/ and then
access either http://192.168.0.4/index.phtml or http://192.168.0.4:8080/,
none of the pages will come up.
I've replicated this on two different setups, and it acts the same everywhere.
index.phtml has nothing but straight html in it, if that matters.
I'm not even going to attempt to guess what's going on here, but I could
really use a smack with the clue brick.
thanks!
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Jonathan Vanasco <jv...@2xlp.com>.
On Jan 30, 2007, at 6:44 PM, Todd Finney wrote:
> The bigger, fancier test case checks all of that.
ok. great. sorry for assuming you didn't have that already -- just
have to be sure.
> What I posted was a simplified test case, in order to demonstrate
> the problem in as few lines of code as possible. I even used as a
> base a code section that should be "known good", as it appears in
> the perldoc for the manual. I thought that I made this pretty
> clear, I'll try harder next time.
well, you said fancy crap. i didn't know what kind of fancy crap.
> Problems such as Apache::Session timing out are unlikely to be the
> culprit, as the problem is reliably reproducible under narrow,
> specific circumstances as outlined in my original message.
> Sessions created under the successful cases never fail, and
> sessions created under the failure cases never succeed. Removing
> the single line in question causes all requests to succeed.
honestly, you'd be surprised. i've seen tons of odd issues with it.
there's definitely an issue with the tied variable then. i've had
that happen before. i can't seem to remember what the issue was.
I'm going through the old listserv articles right now
this *might* give you some ideas
http://www.issociate.de/board/post/309410/
Apache::Session::MySQL_lock_troubles.html
a bunch of the '(X-No-Archive: yes)' deleted posts in that are from
you :)
i remember debugging Apache::Session::MySQL at some point myself ,
and that gave solved some issues. I can't seem to remember where the
issue was. I do recall having the same problem as you at some point
though :(
// Jonathan Vanasco
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
| SyndiClick.com
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
| FindMeOn.com - The cure for Multiple Web Personality Disorder
| Web Identity Management and 3D Social Networking
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
| RoadSound.com - Tools For Bands, Stuff For Fans
| Collaborative Online Management And Syndication Tools
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Todd Finney <tf...@boygenius.com>.
At 05:52 PM 1/30/2007 -0500, Jonathan Vanasco wrote:
>my gut feeling is that you're having an error that deals with valid /
>invalid / new session ids. but it could really be anything - maybe
>you're having connectivity issues with apache::session (timing out ?
>are you using apache::dbi ? etc )
The bigger, fancier test case checks all of that.
----
my %session = ();
$log->info("AccessManagement::Session: tying session");
eval {
tie %session, 'Apache::Session::MySQL',$session_id, {
DataSource=>'dbi:mysql:boygenius',
UserName=>'nobody',
Password=>'XXXXXXXX',
LockDataSource=>'dbi:mysql:boygenius',
LockUserName=>'nobody',
LockPassword=>'XXXXXXXX',
};
};
if ($@) {
$log->info('AccessManagement::Session: '.$@);
undef $session_id;
tie %session, 'Apache::Session::MySQL',$session_id, {
DataSource=>'dbi:mysql:boygenius',
UserName=>'nobody',
Password=>'XXXXXXXX',
LockDataSource=>'dbi:mysql:boygenius',
LockUserName=>'nobody',
LockPassword=>'XXXXXXXX',
};
$log->info('AccessManagement::Session: New Session Created
Successfully.');
}
$log->info('AccessManagement::Session: session id: '.$session_id);
----
It wedges at "AccessManagement::Session: tying session"
What I posted was a simplified test case, in order to demonstrate the
problem in as few lines of code as possible. I even used as a base a code
section that should be "known good", as it appears in the perldoc for the
manual. I thought that I made this pretty clear, I'll try harder next time.
Problems such as Apache::Session timing out are unlikely to be the culprit,
as the problem is reliably reproducible under narrow, specific
circumstances as outlined in my original message. Sessions created under
the successful cases never fail, and sessions created under the failure
cases never succeed. Removing the single line in question causes all
requests to succeed.
>just as an example, in my session class i do:
Yea, thanks.
>anyways, you shouldn't be writing new code for 1.3.x unless you're
>stuck supporting a legacy app.
And thanks again.
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Perrin Harkins <ph...@gmail.com>.
On 1/31/07, Todd Finney <tf...@boygenius.com> wrote:
> I can set it up so that it does the copy->save to pnotes dance for every
> one of the variables, except perhaps for the actual session handle, which
> is stuck into pnotes('SESSION_HANDLE').
If you really need to keep a ref to $session like that, then you
definitely have to use the is_initial_req approach or turn off the
exclusive locking.
- Perrin
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Todd Finney <tf...@boygenius.com>.
At 09:36 AM 1/31/2007 -0500, Perrin Harkins wrote:
>On 1/31/07, Todd Finney <tf...@boygenius.com> wrote:
>>It's responsible for making sure that the client has a session, and it
>>takes any of the values in the session and stores them in pnotes.
>
>Are you sure that you had removed all of these when you did the test
>of copying the session_id, and it still had the same problem?
Now that you mention it, I'm fairly certain that I didn't. That stab was
before I moved to the test case, which means that all of that stuff would
have still been in there. Damn my damnable dumbassery.
I can set it up so that it does the copy->save to pnotes dance for every
one of the variables, except perhaps for the actual session handle, which
is stuck into pnotes('SESSION_HANDLE').
It would appear the using is_initial_req is the best possible solution to
all of this.
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Perrin Harkins <ph...@gmail.com>.
On 1/31/07, Todd Finney <tf...@boygenius.com> wrote:
> It's responsible for making sure that the client has a session, and it
> takes any of the values in the session and stores them in pnotes.
Are you sure that you had removed all of these when you did the test
of copying the session_id, and it still had the same problem?
- Perrin
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Todd Finney <tf...@boygenius.com>.
At 08:29 AM 1/31/2007 -0500, Perrin Harkins wrote:
>On 1/31/07, Todd Finney <tf...@boygenius.com> wrote:
>>Wouldn't throwing a
>> return DECLINED unless $r->is_initial_req;
>>at the top of the handler fix the problem, in that case?
>
>Probably, if you don't actually need this handler to run for the final
>URI. What's the purpose of the handler?
It's responsible for making sure that the client has a session, and it
takes any of the values in the session and stores them in pnotes.
There's an authentication handler further down the line that uses some of
those values (if they exist) to determine whether or not the user has
permission to access the resource. That returns OK unless
is_initial_request, though, so I don't think that a change made in
Session.pm will affect that.
I've gone ahead and added that line, we'll see how it works out.
Thanks for your help, Perrin and Jonathan, I really appreciate it.
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by to...@tuxteam.de.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On Wed, Jan 31, 2007 at 08:29:55AM -0500, Perrin Harkins wrote:
> On 1/31/07, Todd Finney <tf...@boygenius.com> wrote:
> >Wouldn't throwing a
> >
> > return DECLINED unless $r->is_initial_req;
> >
> >at the top of the handler fix the problem, in that case?
>
> Probably, if you don't actually need this handler to run for the final
> URI. What's the purpose of the handler?
>
> >That occurred to me, and one of the first things that I tried was something
> >like this:
> >
> > my $temp_session=$session{_session_id};
> > $r->pnotes('SESSION_ID', $temp_session);
> >
> >It didn't change anything
>
> It was worth a shot. I really thought that would do it though.
If I understood that correctly (which I might quite well not!), if
pnotes takes a ref to whatever is put in, it'll take a ref to the
$session this way too. Maybe you want to put the _session_id in there
(but then, you'll have to cope with the case that the corresponding
session might disapper -- kind of a weak reference).
Regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
iD8DBQFFwX7KBcgs9XrR2kYRAkBCAJ9+0KGWQrStyS/igg3VEk6E46+TbgCfSQcy
YeCsiFXgo5swBMGtJ+7vgL0=
=PKFS
-----END PGP SIGNATURE-----
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Perrin Harkins <ph...@gmail.com>.
On 1/31/07, Todd Finney <tf...@boygenius.com> wrote:
> Wouldn't throwing a
>
> return DECLINED unless $r->is_initial_req;
>
> at the top of the handler fix the problem, in that case?
Probably, if you don't actually need this handler to run for the final
URI. What's the purpose of the handler?
> That occurred to me, and one of the first things that I tried was something
> like this:
>
> my $temp_session=$session{_session_id};
> $r->pnotes('SESSION_ID', $temp_session);
>
> It didn't change anything
It was worth a shot. I really thought that would do it though. Maybe
in your real code there's some additional line that keeps $session
from going out of scope. You could explicitly undef it at the end of
your HeaderParserHandler if that's the case.
- Perrin
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Todd Finney <tf...@boygenius.com>.
At 12:30 AM 1/31/2007 -0500, Perrin Harkins wrote:
>As for what's going wrong, my guess is that it has to do with the
>internal redirects that happen when you access / as opposed to
>/index.phtml. You are trying to open the session in the
>HeaderParserHandler phase, so it's going to open a session, then do an
>internal redirect, and try to open the same session again, effectively
>deadlocking.
Wouldn't throwing a
return DECLINED unless $r->is_initial_req;
at the top of the handler fix the problem, in that case?
>That's a 2.0 doc, but it applies to 1.0 as well: pnotes() increases
>the reference count to $session rather than copying it, so it doesn't
>get destroyed until after the internal redirect has completed and
>pnotes gets torn down. If you use a temporary variable to hold the
>_session_id key, this will not happen and that may fix your problem.
That occurred to me, and one of the first things that I tried was something
like this:
my $temp_session=$session{_session_id};
$r->pnotes('SESSION_ID', $temp_session);
It didn't change anything, so I decided that either (a) that wasn't the
problem, or (b) after years of doing this I *still* don't fundamentally
understand references. Either conclusion made me uncomfortable, so I went
looking for other potential solutions.
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Perrin Harkins <ph...@gmail.com>.
On 1/30/07, Todd Finney <tf...@boygenius.com> wrote:
> The sessions are modified on every request, to set a last_access time, and
> they're modified on login to set an authentication token. I can't think of
> circumstances under which two different requests would attempt to modify a
> given session at the same time.
The biggest risks are things like multiple windows, AJAX calls, or
some kind of auth handler that needs to load the session for every
image request.
> As much as I'd really like to understand what's actually happening here,
> I'll switch to A::S::Lock::Null if you think that's the best bet.
For many people it is, but I can't say for certain if it is for you.
There may be a simpler solution. See below.
> I don't
> see an example in the Apache::Session docs for switching the locking class,
> though - may I have a pointer?
You can either use Apache::Session::Flex or make your own
Apache::Session::MySQL. Open up Apache::Session::MySQL and look at
the code. It's nothing more than a config file. If you copy it,
change the name (and package), and change the name of the locking
class, that will work.
As for what's going wrong, my guess is that it has to do with the
internal redirects that happen when you access / as opposed to
/index.phtml. You are trying to open the session in the
HeaderParserHandler phase, so it's going to open a session, then do an
internal redirect, and try to open the same session again, effectively
deadlocking.
But why does that $r->pnotes call make all the difference? Because
pnotes() is special, as described here:
http://perl.apache.org/docs/2.0/api/Apache2/RequestUtil.html#C_pnotes_
That's a 2.0 doc, but it applies to 1.0 as well: pnotes() increases
the reference count to $session rather than copying it, so it doesn't
get destroyed until after the internal redirect has completed and
pnotes gets torn down. If you use a temporary variable to hold the
_session_id key, this will not happen and that may fix your problem.
I could rant about all the things that bother me about
Apache::Session, but the bottom line is what works for you. Try the
suggestions here and good luck.
- Perrin
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Todd Finney <tf...@boygenius.com>.
At 08:57 PM 1/30/2007 -0500, Perrin Harkins wrote:
>Before I spend too much time analyzing your symptoms, are you sure
>that your application requires excusive locks on sessions? If not,
>you can use Apache::Session::Lock::Null for your locking class.
Eminently reasonable.
>The difference is that without exclusive locks
>you can get lost updates if a user tries to modify a session from two
>separate requests simultaneously. (Not usually an issue, but it can
>be for certain kinds of applications.)
The sessions are modified on every request, to set a last_access time, and
they're modified on login to set an authentication token. I can't think of
circumstances under which two different requests would attempt to modify a
given session at the same time.
As much as I'd really like to understand what's actually happening here,
I'll switch to A::S::Lock::Null if you think that's the best bet. I don't
see an example in the Apache::Session docs for switching the locking class,
though - may I have a pointer?
thanks!
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Perrin Harkins <ph...@gmail.com>.
On 1/30/07, Todd Finney <tf...@boygenius.com> wrote:
> - When I fire up a new browser and access http://192.168.0.4/, the browser
> hangs. In my bigger fancier handler with more detailed logging, it seems
> to hang right before the session tie.
Any time that Apache::Session hangs, it's because of the excusive
locking that it does. It tries to get a lock when you call tie(), and
if another session object with the same ID is already holding that
lock, it will hang. A glance at your problem description makes it
sound like there could be internal redirects happening, while the
parent request holds onto its session and lock, causing a hang.
Before I spend too much time analyzing your symptoms, are you sure
that your application requires excusive locks on sessions? If not,
you can use Apache::Session::Lock::Null for your locking class. You
will not get any data corruption because MySQL already insures that
updates are atomic. The difference is that without exclusive locks
you can get lost updates if a user tries to modify a session from two
separate requests simultaneously. (Not usually an issue, but it can
be for certain kinds of applications.)
- Perrin
Re: Apache::Session::MySQL, light/heavy proxy, wedging
Posted by Jonathan Vanasco <jv...@2xlp.com>.
On Jan 30, 2007, at 4:47 PM, Todd Finney wrote:
> I have two servers running in the light/heavy configuration as
> outlined in the guide. Both servers are 1.3.34. On the
> lightweight server, my proxy section looks like this:
first off, you should be running 2.0.x by now
try this:
> my %session;
eval {
> tie %session, 'Apache::Session::MySQL', $cookie, {
> DataSource => 'dbi:mysql:boygenius', #these arguments are
> UserName => 'nobody', #required when using
> Password => 'XXXXXXXXX', #MySQL.pm
> LockDataSource => 'dbi:mysql:boygenius',
> LockUserName => 'nobody',
> LockPassword => 'XXXXXXXXX'
> };
};
if ( $@ ) {
print STDERR "\n ERROR TIE -> $@ ";
}
> I'm not even going to attempt to guess what's going on here, but I
> could really use a smack with the clue brick.
my gut feeling is that you're having an error that deals with valid /
invalid / new session ids. but it could really be anything - maybe
you're having connectivity issues with apache::session (timing out ?
are you using apache::dbi ? etc )
just as an example, in my session class i do:
is there a cookie ? if so, is the session id in a valid format .
if so, is it a valid session.
no session id ? then i need a session new. can i crete a new
session ? yes ? awesome. no ? log an error and do something for
unsupported sessions ( ie , send a notifier to the daemon that will
email me if it gets more than 10 of those in an hour and regardless-
redirect the user to a "system error" page )
anyways, you shouldn't be writing new code for 1.3.x unless you're
stuck supporting a legacy app.
// Jonathan Vanasco
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
| SyndiClick.com
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
| FindMeOn.com - The cure for Multiple Web Personality Disorder
| Web Identity Management and 3D Social Networking
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
| RoadSound.com - Tools For Bands, Stuff For Fans
| Collaborative Online Management And Syndication Tools
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -