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

Here is my problem. As best as I can make out, an flock on a file dissolves as soon as the process that created it ends. That means that when using CGI.pm I cannot normally create an flock in one form handler and release it in another.

I am thinking that one solution would be to use fork in a creative manner. However, I have never used fork before and suspect that there may be a less complex way to share a file handle and its lock from one form handler to another. Has anyone out there been able to create persistent exclusive file locks while running CGI.pm?

  • Comment on Can I Create A Persistent Flock Under CGI.pm?

Replies are listed 'Best First'.
Re: Can I Create A Persistent Flock Under CGI.pm?
by japhy (Canon) on May 30, 2001 at 00:25 UTC
    Use a semaphore as the lock. I like using directories for this, because mkdir() is atomic (unless you do it over NFS).
    sub LOCK { sleep 1 until mkdir "$_[0].lck", 0755 } sub UNLOCK { rmdir "$_[0].lck" }
    Now you just use those, and they exist over multiple calls to the program.

    japhy -- Perl and Regex Hacker
      The more I think about semaphores the more I am concerned about a web user who walks away or logs out after the first form is submitted. His semaphore could go on living forever!

      It may be that when using basic authentication and multi-page forms and multiple sessions with the same login id there is no simple solution to the problem of only allowing one session to use a file at a time.

        Using a unique filename will ensure that someone won't block access to the form and that data won't bleed together and it's almost as simple as using a semaphore. You don't even need to use cookies, just add the unique id to the path_info and read it from there if you want. (Just make sure CGI.pm is outputting the Form HTML).

        As far as untainting the passed sessionid, you could do the following.
        path_info() =~ /^(\w+)/; my $session_id = $1; unless ($session_id){ # Session doesn't exist so they are new user. $session_id = makesessionID(); # Create file and display first form below }else{ unless (-e $my_path.$session_id){ # Something is funny if the session doesn't exist. # Probably should die } # Read in session data from file. # Form two (3,4,5 whatever) below. }


        Just my two cents.

        -Lee

        "To be civilized is to deny one's nature."
Re: Can I Create A Persistent Flock Under CGI.pm?
by chromatic (Archbishop) on May 29, 2001 at 23:23 UTC
    In general Perl terms, a flock persists until you release it, or you close the filehandle. The recommended approach is to close the filehandle and let Perl clean up for you. If you don't close explicitly, Perl will do that for you when the process exits.

    With regard to sharing a lock with multiple scripts, you may as well not flock at all. What's the point? A lock is there to prevent concurrent access from corrupting your data or your file. If you allow more than once process to access a single lock at a time, you've subverted that.

    I suspect there's a better way to accomplish the goal, but it's hard to see what the goal actually is. :)

      The Requirement: Allow a user to submit Form #1 that saves a stored CGI query object and presents the user with Form #2. When the user submits Form #2 it should retrieve the query object saved by Form #1, read its data and then delete the flat file that stores the query object.

      The Problem: What if the user logs in twice and submits Form #1 twice in a row? Then information from one login's submittal could bleed into the next. But if Form #1 could gain an exclusive lock on the query object file and hold it until Form #2 releases it then the problem would be solved: the potential race condition would be avoided because the second login would never get to submit Form #1 if someone else had locked it.