in reply to CGI::Session disconnect invalidates 1 active statement handle

Hi everyone. I realized the close() method was deprecated with flush when reading the docs. I remember actually using flush() first just to see if it would get rid of the error, then decided to try close for the heck of it.

As with jZed, I'll take your advice and try to better indent my coding.

I decided not to use cookies and have it keep loading the session via db (sessions expire after 30mins no matter what..this app will not be used my many).

Kurt, I think I know what you mean. I can prob modify CGI::Session so that it adds a expire_time field to the database, and then I can just check against that time vs, the E_TIME stored by CGI::Session. I think I read an example here, Re: Listing Active CGI::Sessions, before writing this little cron script.

I was going to do this option, but thought it wasn't too necessary if I could get my first method right.

I fixed my following code so it looks like this:
use DBI; my $dbh = DBI->connect($main::location, $main::user, $main::ba_pas +s, { RaiseError => 1, AutoCommit => 1}) or die "Couldn't connect to d +atabase: " . $DBI::errstr; eval { my $sth= $dbh->prepare("SELECT id FROM sessions"); my $id; $sth->execute(); $sth->bind_columns(undef, \$id); require CGI::Session; import CGI::Session; while ($sth->fetch()) { my $session = CGI::Session->load("driver:MySQL", $id, {Handle=>$ +dbh}); next if $session->is_empty; if (($session->ctime + $session->etime) <= time()) { $session->delete(); } } }; if ($@) { print $@; $dbh->disconnect(); }
Still a bit concerned since it doesn't have $dbh->disconnect anymore inside the eval. I'm relying on it existing and disconnecting when it detects the end of my script. The above code generates no errors or warnings and my cron script can run w/out e-mailing me the output of the error all the time. At most, it will only detect about 3-20 sessions a given day.

Notice I still use the load method vs. the new method of CGI::Session. I thought the load method was intentionally for this purpose (to only load and read vs, using new to create/edit/append).

From the CGI::Session manual:
load() is useful to detect expired or non-existing sessions without forcing the library to create new sessions.

Also , I hope my indenting is a bit better. :)

Replies are listed 'Best First'.
Indentation Style
by jZed (Prior) on Jul 08, 2007 at 07:01 UTC
    Hi perleager. I didn't mean to sound too harsh, and it's not like indenting is the most important thing and tastes vary. But in a chunk of code like you have, I find it most useful to indent mostly based on blocks -- start the indent with the opening "{" of the block and end the indent with the closing "}". This lets you see at a glance which block each line is part of and also to easily check to make sure you didn't omit a curly brace. I sometimes also indent arguments to functions using the opening and closing parentheses to see where to indent. Here's how I would indent your code (again, tastes vary, this is just my way):
    use DBI; my $dbh = DBI->connect( $main::location, $main::user, $main::ba_pass, {RaiseError=>1,AutoCommit=>1} ) or die "Couldn't connect to database: " . $DBI::errstr; # # indent one level for the eval block # eval { my $sth= $dbh->prepare("SELECT id FROM sessions"); my $id; $sth->execute(); $sth->bind_columns(undef, \$id); require CGI::Session; import CGI::Session; # # indent a second level for the while block # while ($sth->fetch()) { my $session = CGI::Session->load( "driver:MySQL", $id, {Handle=>$dbh} ); next if $session->is_empty; # # indent a third level for the if block # if (($session->ctime + $session->etime) <= time()) { $session->delete(); } } }; if ($@) { print $@; $dbh->disconnect(); }

    update:renamed it so I could find it :-)