Mandor has asked for the wisdom of the Perl Monks concerning the following question:

While working at a local web project I came across a point
where I thought session handling could come in handy and
so I installed Apache::Session. I set up some cookie routines
and then went testing the whole thing. The first request
to my script correctly noticed that there is no session yet and
thus created the correct HTTP-Header. But the second request
didn't seem to finish. Looking at my process list I noticed that
a perl process was running and seemingly would not quit.
When I killed the process the output of the script was finally
send to the browser.
Eager to know what was going on I set up my Apache server and
Activestate's Komodo for remote debugging to see what was going on.
I noticed that the script was running fine through my code parts
but after the last line the DESTROY routine of Apache::Session::File
was called. I compiled the following list that shows the way the script
takes. The last line is a goto command that seemingly doesn't finish.

The list :
# line 38 Apache::Session::File sub DESTROY { ... $self->save; # leaves here to Apache::Session ... } # line 489 Apache::Session sub save { ... return unless ( $self->{status} & MODIFIED || #leaves here to line 313 ... # line 313 Apache::Session sub MODIFIED () {2}; # off to line 497 (sub save) # line 497 Apache::Session sub save { ... $self->acquire_write_lock; # up up and away to line 565 ... # line 565 Apache::Session sub acquire_write_lock { ... return if ($self->{lock} & WRITE_LOCK); # see you at line 539 ... # line 539 Apache::Session sub WRITE_LOCK () {2}; # off to line 569 (sub acquire_write_lock) # line 569 Apache::Session sub acquire_write_lock { ... $self->{lock_manager}->acquire_write_lock($self); # We are slow +ly closing into ... # Apache::S +ession::File::Lock # line 51 # line 51 Apache::Session::File::Lock sub acquire_write_lock { ... flock($self->{fh}, LOCK_EX); # GOTO Fcntl line 203 (AUTOLOAD) # line 203 Fcntl sub AUTOLOAD { ... goto &$AUTOLOAD; # That's all folks. This one won't work.
Am I doing something wrong? For reference
here is a modified version of my package that handles the cookie stuff :
package Request; use strict; use base 'Exporter'; use vars qw(@EXPORT); @EXPORT = qw ( handle_session ... ); use Apache::Session::File; use CGI; sub handle_session { my $cgi = CGI -> new; my %session; my $session_cookie = $cgi -> cookie ('SID'); tie %session, 'Apache::Session::File', $session_cookie, { Directory => "../data/sessions", LockDirectory => "../data/sessions" }; unless ($session_cookie) { my $session_cookie = $cgi -> cookie ( -name =>'SID', -value => $sessio +n{_session_id} ); print $cgi -> header (-cookie => $session_cookie); print 'Mmmhh.. Cookie'; # debug purpose } else { print $cgi -> header; print 'No cookie for you!'; #debug purpose } return \%session; } 1;
I am using Apache 1.3.xx, ActiveState perl 631, Win32 and the
newest Apache::Session version (I think).
.pl files are handled by CGI at the moment but changing the handling to PerlRun for example didn't help.

I am thankful for a helping hand.

Replies are listed 'Best First'.
Re: Apache::Session hangs
by converter (Priest) on Mar 02, 2002 at 13:03 UTC

    This is probably not directly related to the problem you're experiencing, but for what it's worth, the Apache::Session documentation says:

    When Session encounters an error, it calls die(). You will probably w +ant to wrap your session logic in an eval block to trap these errors.

    He's not kidding. If you supply the TIEHASH method with either a funky session ID, or a session ID for which there is no session in the store, Session dies. Do something like this to handle potential exceptions:

    eval { tie %session, 'Apache::Session::File', $session_cookie, { Directory => "../data/sessions", LockDirectory => "../data/sessions" }; }; if ($@) { # since the first attempt failed, supply the # undefined value as the session ID argument # so that Session will generate a new session tie %session, 'Apache::Session::File', undef, { Directory => "../data/sessions", LockDirectory => "../data/sessions" } }

    Also, since you're a smart Perl developer and you're using taint mode, you'll want to untaint the session ID before passing it to Apache::Session. The session ID is inserted in session filenames and lock filenames, and Perl will raise an exception if you don't untaint it.

    Update:

    For what it's worth, it doesn't look like Apache::Session has even been tested on Win32. test report.

    If you're having a problem with Fcntl, you might look into Apache::Session::Flex, which should allow you to use your own file locking code. You may be able to use File::FlockDir to do most of the work.

      The trouble with your eval here is that it doesn't check to see what the problem was. It could be something totally unrelated to the error that Apache::Session throws, like a full disk or bad file permissions or any number of other things. You can check to see if what's you think it is with something like this:
      if ($@ =~ m#^Object does not exist in the data store#)
      Thank you for your suggestions. While it didn't fix the problem it certainly helps to improve my code (stupid me forgot about taint mode). If anyone has a idea why I encounter the problem (and how it could be fixed) that would make me a real happy man.
Apache::SessionX
by tjmather (Initiate) on Mar 02, 2002 at 17:14 UTC
    You may want to try Apache::SessionX, an extension of Apache::Session. It has several useful features, including the ability to create a new session when the session ID doesn't exist, by setting create_unknown.
Re: Apache::Session hangs
by perrin (Chancellor) on Mar 02, 2002 at 17:27 UTC
    Fcntl might not work on Windows. Why don't you try using NullLocker instead (as the previous poster suggested with Apache::Session::Flex) and find out if that's the problem or not?
Re: Apache::Session hangs
by Mandor (Pilgrim) on Mar 02, 2002 at 18:27 UTC
    Thank you for your help folks. I tried Apache::Session::Flex and it seems to work now. Thanks.