[Rt-commit] rt branch, 4.0/file-based-session-locks, created. rt-4.0.12-18-g125848b

Thomas Sibley trs at bestpractical.com
Thu May 16 04:37:27 EDT 2013


The branch, 4.0/file-based-session-locks has been created
        at  125848b02327cf5f3f23084d786a8a8a8c127e85 (commit)

- Log -----------------------------------------------------------------
commit 5ab23daca4db2ef54fb5973b0b7b886a299a9e18
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Thu May 16 01:08:06 2013 -0700

    Correct a misspelling in log messages

diff --git a/lib/RT/Interface/Web/Session.pm b/lib/RT/Interface/Web/Session.pm
index 4edd9bd..ddbcef5 100644
--- a/lib/RT/Interface/Web/Session.pm
+++ b/lib/RT/Interface/Web/Session.pm
@@ -192,7 +192,7 @@ sub _ClearOldDB {
         die "couldn't execute query: ". $dbh->errstr unless defined $rows;
     }
 
-    $RT::Logger->info("successfuly deleted $rows sessions");
+    $RT::Logger->info("successfully deleted $rows sessions");
     return;
 }
 
@@ -222,7 +222,7 @@ sub _ClearOldDir {
             next;
         }
         tied(%session)->delete;
-        $RT::Logger->info("successfuly deleted session '$id'");
+        $RT::Logger->info("successfully deleted session '$id'");
     }
 
     my $lock = Apache::Session::Lock::File->new;
@@ -259,7 +259,7 @@ sub ClearByUser {
             }
         }
         tied(%session)->delete;
-        $RT::Logger->info("successfuly deleted session '$id'");
+        $RT::Logger->info("successfully deleted session '$id'");
     }
 }
 

commit 125848b02327cf5f3f23084d786a8a8a8c127e85
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Thu May 16 01:25:34 2013 -0700

    Clean orphaned session file locks more aggressively
    
    When using file-based sessions, lock files are orphaned once the session
    is deleted through any call to tied(%session)->delete, such as logging
    out.  These lock files continue to accumulate until the session cleaner
    eventually picks them after a set age.
    
    Over the course of even a relatively short, and common, 7 day max age
    limit, the accumulated orphaned locks on a busy site (combined with all
    the active sessions + locks) can bloat the size of the session directory
    beyond the capacity of a standard ext3/4 filesystem directory entry.
    Once this happens, sessions will start to fail sporadically with "No
    space left on device" errors, despite plenty of disk space being
    available.
    
    Once a lock file is orphaned, it is safe to delete regardless of its
    age.  Aggressively remove such locks whenever the session cleaner runs.
    
    Arguably this should be handled inside Apache::Session when ->delete is
    called.  Until then, the extra cleaning is simple to implement.

diff --git a/lib/RT/Interface/Web/Session.pm b/lib/RT/Interface/Web/Session.pm
index ddbcef5..0d70ac7 100644
--- a/lib/RT/Interface/Web/Session.pm
+++ b/lib/RT/Interface/Web/Session.pm
@@ -225,12 +225,50 @@ sub _ClearOldDir {
         $RT::Logger->info("successfully deleted session '$id'");
     }
 
+    # Apache::Session::Lock::File will clean out locks older than X, but it
+    # leaves around bogus locks if they're too new, even though they're
+    # guaranteed dead.  On even just largeish installs, the accumulated number
+    # of them may bump into ext3/4 filesystem limits since Apache::Session
+    # doesn't use a fan-out tree.
     my $lock = Apache::Session::Lock::File->new;
     $lock->clean( $dir, $older_than );
 
+    # Take matters into our own hands and clear bogus locks hanging around
+    # regardless of how recent they are.
+    $self->ClearOrphanLockFiles($dir);
+
     return;
 }
 
+=head3 ClearOrphanLockFiles
+
+Takes a directory in which to look for L<Apache::Session::Lock::File> locks
+which no longer have a corresponding session file.  If not provided, the
+directory is taken from the session configuration data.
+
+=cut
+
+sub ClearOrphanLockFiles {
+    my $class = shift;
+    my $dir   = shift || $class->Attributes->{Directory}
+        or return;
+
+    if (opendir my $dh, $dir) {
+        for (readdir $dh) {
+            next unless /^Apache-Session-([0-9a-f]{32})\.lock$/;
+            next if -e "$dir/$1";
+
+            RT->Logger->debug("deleting orphaned session lockfile '$_'");
+
+            unlink "$dir/$_"
+                or warn "Failed to unlink session lockfile $dir/$_: $!";
+        }
+        closedir $dh;
+    } else {
+        warn "Unable to open directory '$dir' for reading: $!";
+    }
+}
+
 =head3 ClearByUser
 
 Checks all sessions and if user has more then one session
@@ -243,6 +281,7 @@ sub ClearByUser {
     my $class = $self->Class;
     my $attrs = $self->Attributes;
 
+    my $deleted;
     my %seen = ();
     foreach my $id( @{ $self->Ids } ) {
         my %session;
@@ -260,7 +299,9 @@ sub ClearByUser {
         }
         tied(%session)->delete;
         $RT::Logger->info("successfully deleted session '$id'");
+        $deleted++;
     }
+    $self->ClearOrphanLockFiles if $deleted;
 }
 
 sub TIEHASH {

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


More information about the Rt-commit mailing list