I did some digging of my own. Here is what I found.
Function load begins:
sub load {
my $class = shift;
return $class->set_error( "called as instance method") if ref $
+class;
return $class->set_error( "Too many arguments provided to load()")
+ if @_ > 5;
my $self = bless {
_DATA => {
_SESSION_ID => undef,
_SESSION_CTIME => undef,
_SESSION_ATIME => undef,
_SESSION_REMOTE_ADDR => $ENV{REMOTE_ADDR} || "",
#
# Following two attributes may not exist in every single s
+ession, and declaring
# them now will force these to get serialized into databas
+e, wasting space. But they
# are here to remind the coder of their purpose
#
# _SESSION_ETIME => undef,
# _SESSION_EXPIRE_LIST => {}
}, # session data
_DSN => {}, # parsed DSN params
_OBJECTS => {}, # keeps necessary objects
_DRIVER_ARGS=> {}, # arguments to be passed to driver
_CLAIMED_ID => undef, # id **claimed** by client
_STATUS => STATUS_UNSET,# status of the session object
_QUERY => undef # query object
}, $class;
Here we see that _STATUS is part of _DATA. Then, a little further on in load, where it checks for whether or not the session has timed out, we have:
# checking for expiration ticker
if ( $self->{_DATA}->{_SESSION_ETIME} ) {
if ( ($self->{_DATA}->{_SESSION_ATIME} + $self->{_DATA}->{_SES
+SION_ETIME}) <= time() ) {
$self->_set_status( STATUS_EXPIRED | # <-- so client ca
+n detect expired sessions
STATUS_DELETED ); # <-- session shou
+ld be removed from database
$self->flush(); # <-- flush() will
+ do the actual removal!
return $self;
}
}
Which, I believe you quoted. But then in flush, we have:
sub flush {
my $self = shift;
# Would it be better to die or err if something very basic is wron
+g here?
# I'm trying to address the DESTROY related warning
# from: http://rt.cpan.org/Ticket/Display.html?id=17541
# return unless defined $self;
return unless $self->id; # <-- empty session
# neither new, nor deleted nor modified
return if !defined($self->{_STATUS}) or $self->{_STATUS} == STATUS
+_UNSET;
if ( $self->_test_status(STATUS_NEW) && $self->_test_status(STATUS
+_DELETED) ) {
$self->{_DATA} = {};
return $self->_unset_status(STATUS_NEW | STATUS_DELETED);
}
my $driver = $self->_driver();
my $serializer = $self->_serializer();
if ( $self->_test_status(STATUS_DELETED) ) {
defined($driver->remove($self->id)) or
return $self->set_error( "flush(): couldn't remove session
+ data: " . $driver->errstr );
$self->{_DATA} = {}; # <-- removing all
+ the data, making sure
# it won't be acce
+ssible after flush()
return $self->_unset_status(STATUS_DELETED);
}
if ( $self->_test_status(STATUS_NEW | STATUS_MODIFIED) ) {
my $datastr = $serializer->freeze( $self->dataref );
unless ( defined $datastr ) {
return $self->set_error( "flush(): couldn't freeze data: "
+ . $serializer->errstr );
}
defined( $driver->store($self->id, $datastr) ) or
return $self->set_error( "flush(): couldn't store datastr:
+ " . $driver->errstr);
$self->_unset_status(STATUS_NEW | STATUS_MODIFIED);
}
return 1;
}
In the block that begins with "if ( $self->_test_status(STATUS_DELETED) ) {", we have "$self->{_DATA} = {};". Doesn't this have the effect of blowing away the "STATUS_EXPIRED" status, resulting in a false value being returned by is_expired because it is checking against a member in the hash that does not exist after the flush when the status has been given a status of DELETED?
Thanks
Ted