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

I am using the mojolicious framework for some web applications. I am getting an error sometimes when users access my application. I create a session file in /data/app/tmp/sessions/randomfile. I am getting the following error [error] can't get shared lock on /data/app/tmp/sessions/randomfile: Resource temporarily unavailable at /usr/share/perl5/Plack/Session/Store/File.pm line 27. The File.pm file line 27 is $params{'deserializer'} ||= sub { Storable::lock_retrieve( @_ ) };. Sometimes it happens on line 26 of the file, line 26 is the serializer. server: hypnotoad os: ubuntu 16 If the user deletes the cookie it works. However it does occur again. Any one seen any weird behavior like this?

Replies are listed 'Best First'.
Re: Perl temporarily unavailable error
by stevieb (Canon) on Aug 31, 2020 at 21:09 UTC

    Sounds very much like synchronous disk accesses causing lock contention.

    Changing to a proper database system would likely fix the issue. Beyond that thought, perhaps share some info such as number of hits, disk activity information, file permissions etc.

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Perl temporarily unavailable error
by jcb (Parson) on Sep 01, 2020 at 01:39 UTC

    When the users delete their cookies, they get new sessions and the old session files are abandoned. (I assume that randomfile is a random file name and that you are not storing every session in a file literally named randomfile.)

    I will guess that every request carries the session cookie and the errors occur due to simultaneous requests (for images or other supporting resources) and your application is not being sufficiently careful with session handling, causing locking conflicts. Something like:

    1. User requests /foo
    2. /foo is HTML referencing /foo.css and /bar.png
    3. User's browser initiates concurrent requests for those resources, possibly while still retrieving /foo itself
    4. Server handles requests concurrently, attempting to load session data for the secondary requests and colliding with the session update lock as the retrieval of /foo completes

    The answer is either to avoid loading the session for subsidiary requests or to use a session store with better concurrent access performance. PostgreSQL usually works very well.

      Figured out the issue. Plack session use Storable by default. Looking at the documentation I found. if you share your files across NFS, you might wish to use other forms of locking by using modules such as LockFile::Simple which lock a file using a filesystem entry, instead of locking the file descriptor. I am using a NFS, so that was causing the issue. I switched to a different method and that has worked. I did look at trying the database way but I couldn't get anything to work.
      use Plack::Session::Store::DBI; $self->plugin('SessionStore' => Plack::Session::Store::DBI->new( dbh => DBI->connect(connection stuff), table_name => 'my_session_table', )); #my table CREATE TABLE my_sessions_table (id VARCHAR(100) PRIMARY KEY,session_da +ta TEXT);
      I did not receive any errors. What am I doing incorrectly.

        You should have said that you were using NFS. Locking on NFS is hit-or-miss at times and we would have told you to suspect that as a likely cause and try running with the session store on a local disk. If you are using a load balancer, all you need to do is arrange for load balancing to be deterministic, either by session token (ideal) or client address, and then each worker only needs to care about its user's sessions.

      Great response. Well thought out and presented. I'd point to one of your statements specifically that I agree with: "use a session store with better concurrent access performance."