All:

I'm getting very odd behavior out of Apache::Session, with 
serious problems using both the MySQL and File variants.

Yes, I know I've come here with this problem before.  Sigh.
I even fixed it, although it was one of those things where I 
didn't quite know why it started working.  Anyway, it stopped
working about a week ago, and, as usual, I have no clue.  Hence
this plea for help:

With Apache::Session::File, this code creates a new session id
with every request.  The lock file for each session remains in
the lock directory.  I ran a 'chmod -R 777 <dirname>' on both
the session store and lock directories.

With Apache::Session::MySQL, this code behaves more normally:
it reuses the session id, the way [I believe] it should, except
$session{state} never seems to make it into the database.  I
say that because I look at the contents of the sessions table 
between transactions, and it looks like this:

mysql> select * from sessions;
+----------------------------------+-----------------------------------------------------------+
| id                               |
a_session                                                 |
+----------------------------------+-----------------------------------------------------------+
| 4def39f4e8144aede90532951232c040
|                                                         |
+----------------------------------+-----------------------------------------------------------+
1 row in set (0.00 sec)

I did make sure that the right privileges existed for the 
database user accessing the sessions table.

I tried uninstalling Apache::Session ('rm -rf 
/usr/local/lib/perl5/site_perl/5.6.0/Apache/Session*'),
and reinstalled it using CPAN, on the theory that I may have 
diddled it while checking out its code.  But that didn't help.

Here's the (relevant) code, with short, annotated, log extract 
following:

##
## Physemp::Search
##
package Physemp::Search;

use strict;

use Apache;
use Apache::Request;
use Apache::Constants qw( :common );
use CGI::Cookie;
use Apache::Session::MySQL;
use DBI;
use Data::Dumper;

my (%states, %_CACHE);

sub handler ($$) {
  my ($class, $q) = @_;
  my $self = $class->new(my $r = Apache::Request->new($q));
  my $html = '';
  $self->get_session($r);
  my $coderef =
$self->{make}->{$self->frame}->{$self->page}->{$self->command}
                || \&unimplemented;
  $html = $self->$coderef($r);
  
  $r->content_type('text/html');
  $self->put_or_del_session($r);
  $r->send_http_header;
  print $html;
  return OK;
}

sub get_session {
  my ($self, $r) = @_;

  my %session;

  my $cookie_str = $r->header_in('Cookie');
  my %cookies = $cookie_str eq '' ? ( ) :
CGI::Cookie->parse($cookie_str);
  if (exists $cookies{SessionID}) {
    (my $session_id = $cookies{SessionID}->value) =~ s/([0-9a-f]+)/$1/;
    eval {
      tie %session, $self->{tieclass}, $session_id, $self->{tieattrs};
    };
    if ($@) { 
      $r->log_error($@);
      $r->log_error("get_session: No session data found.");
      $self->{state}      = { };
      $self->{session_id} = '';
    } else {
      $r->log_error("get_session: Session data found.");
      $r->log_error("get_session: \$session{state} is \n", Dumper
$session{state});
      $session{state} = { account => {} } unless exists $session{state};
      $self->{session_id} = $session{_session_id};
      $self->{state}      = $session{state};
    }
    undef %session;
  } else {
    $r->log_error("get_session: No Session ID cookie.");
    $self->{state}      = { };
    $self->{session_id} = '';
  }
  $r->log_error("get_session: Session ID is '$self->{session_id}'.");
  $r->log_error("get_session: State is \n", Dumper $self->{state});
}

sub put_or_del_session {
  my ($self, $r) = @_;

  my (%session, $cookie);

  if ($self->command eq 'make' or $self->page eq 'action') {
    eval {
      tie %session, 
          $self->{tieclass}, 
          ($self->{session_id} eq '' ? undef : $self->{session_id}), 
          $self->{tieattrs};
    };
    if ($@) { 
      $r->log_error("put_or_del_session: $@");
      eval { tie %session, $self->{tieclass}, undef, $self->{tieattrs};
};
      if ($@) {
        $r->log_error("put_or_del_session: $@");
        return;                         # WTH, we can't do any good here
      }
    } 
    if ($self->command eq 'logout') {
      $r->log_error("put_or_del_session: deleting session.");
      $cookie = CGI::Cookie->new( -name    => 'SessionID', 
                                  -path    => $self->{uri}, 
                                  -domain  => '.physemp.com',
                                  -expires => '-10m',
                                  -value   => '' );
      tied(%session)->delete;
    } else {
      $r->log_error("put_or_del_session: updating session.");
      $session{state} = $self->{state};
      $session{changes}++;   
      $r->log_error("put_or_del_session: Session ID is
'$session{_session_id}'.");
      $r->log_error("put_or_del_session: State is \n", Dumper
$session{state});
      $cookie = CGI::Cookie->new( -name    => 'SessionID', 
                                  -path    => $self->{uri}, 
                                  -domain  => '.physemp.com',
                                  -expires => '+1M',
                                  -value   => $session{_session_id} );
    }
    undef %session;
    $r->headers_out->add('Set-Cookie' => $cookie->as_string);
  }
}

sub new {
  my ($class, $r) = @_;

  my $uri = $r->uri;
  unless (exists $_CACHE{$uri}) {
    my (%make, %db, %config);

    # %make, %db, %config filled in here

    #my %tiehash = ( 
    #  DataSource     => $config{Session_DB}, 
    #  UserName       => $config{Search_DB_User},
    #  Password       => $config{Search_DB_Password},
    #  LockDataSource => $config{Session_DB}, 
    #  LockUserName   => $config{Search_DB_User},
    #  LockPassword   => $config{Search_DB_Password},
    #);
    my %tiehash = ( 
      Directory     => $config{Session_Info_Dir},
      LockDirectory => $config{Session_Lock_Dir},
    );
    
    my $self = {
                 config   => \%config,
                 make     => \%make,
                 db       => \%db,
                 tieclass => 'Apache::Session::File',
                 tieattrs => \%tiehash,
                 uri      => $uri,
               };

    $_CACHE{$uri} = bless $self, $class;
  }
  my $self = $_CACHE{$uri};

  $self->{frame}   = $r->param('frame')   || 'search';
  $self->{page}    = $r->param('page')    || 'main';
  $self->{command} = $r->param('command') || 'make';

  return $self;
}

sub unimplemented {
  my ($self, $r) = @_;

  $r->log_reason("Tried to Access $self->{uri} with params: 
frame=$self->{frame}\&page=$self->{page}\&command=$self->{command};");
  $r->status(FORBIDDEN);
  return '';
}

return 1;
    
##
## end Physemp::Search code
##

begin annotated log extracts with MySQL
---------------------------------------

# Begining with the initial request:
[Sun Apr 29 00:53:26 2001] [error] get_session: Session data found.
[Sun Apr 29 00:53:26 2001] [error] get_session: $session{state} is 
$VAR1 = undef;  # $session{state} isn't there
[Sun Apr 29 00:53:26 2001] [error] get_session: Session ID is
'ee9eee6e0b7cb3ca9c7cb13cc1585c22'.
# but we do have a _session_id
[Sun Apr 29 00:53:26 2001] [error] get_session: State is 
$VAR1 = {'account' => {}};
# if I don't have a $session{state}, I create a default one here.
# now we're going to try updating: the session_id and state information
is dumped to the log
[Sun Apr 29 00:53:26 2001] [error] put_or_del_session: updating session.
[Sun Apr 29 00:53:26 2001] [error] put_or_del_session: Session ID is
'ee9eee6e0b7cb3ca9c7cb13cc1585c22'.
[Sun Apr 29 00:53:26 2001] [error] put_or_del_session: State is 
$VAR1 = {
          'account' => {},
          'search' => {
                        'params' => {
                                      'area' => 'KS',
                                      'specialty' => 'Family Practice',
                                      'results_per_page' => '5',
                                      'type' =>
'by-specialty-area-visa',
                                      'visa' => 'Citizen,Greencard'
                                    },
                        'page' => 0,
                        'results' => [
                                       ['7763','Joel
Jones','Yes','Yes','Yes','2004'],
                                       ['7656','Charles R.
Mitchell','Yes','Yes','Yes','1997'],
                                       ['7579','Christopher
Maxwell','Yes','Yes','Yes','2002'],
                                       ['7401','Jeffrey F.
Roylance','Yes','Yes','Yes','2003'],
                                       ['6801','Rajesh V.
Patel','Yes','No','Yes','1995'],
                                       ['6546','Ronald Fisher,
D.O.','Yes','Yes','Yes','1999'],
                                       ['6404','Mike
Stevenson','Yes','Yes','Yes','1985'],
                                       ['6266','Martin
Falappino','Yes','No','Yes','1998'],
                                       ['6217','Scott D. Marrs,
D.O.','Yes','Yes','Yes','1990'],
                                       ['6079','Gillian
O\'brady-Henry','Yes','Yes','Yes','1998'],
                                       ['5940','Marc C.
Mentel','Yes','Yes','Yes','1997'],
                                       ['5174','Mike
Myers','Yes','Yes','Yes','1998'],
                                       ['5176','Marc E.
Enyart','Yes','Yes','Yes','2001'],
                                       ['5182','Curtis John
Wood','Yes','Yes','Yes','1986'],
                                       ['4639','Timothy L. Wilson,
M.D.','Yes','Yes','Yes','1987'],
                                       ['4595','Kevin B. Lane,
D.O.','Yes','Yes','Yes','1995'],
                                       ['4339','Dr Christina K.
Jones','Yes','Yes','Yes','1999'],
                                       ['4184','Dr. Donald
Mcgrorey','Yes','Yes','Yes','1993'],
                                       ['4141','Anthony R.
Justesen','Yes','Yes','Yes','2000'],
                                       ['4029','M
Murry','Yes','Yes','Yes','2003'],
                                       ['3954','Gene
Duquette','Yes','Yes','Yes','2002'],
                                    ],
                        'last_page' => 14
                      }
        };
# ok, session state should bve in mySQL, right?
[Sun Apr 29 00:54:10 2001] [error] get_session: Session data found.
[Sun Apr 29 00:54:10 2001] [error] get_session: $session{state} is 
$VAR1 = undef;
# but it's not, wheee! :(
[Sun Apr 29 00:54:10 2001] [error] get_session: Session ID is
'ee9eee6e0b7cb3ca9c7cb13cc1585c22'.
[Sun Apr 29 00:54:10 2001] [error] get_session: State is 
$VAR1 = {
          'account' => {}
        };

-------------------------------------------------------

Any ideas?

  --Christopher

Reply via email to