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

I have a script where during a short period of time near the middle of the script I need only one user to be able to access it at a time. Is it possible to use 'flock' to have a script temporarily lock itself? If not what other possiblities are there?

thanks, steve

Replies are listed 'Best First'.
Re: Locking a script
by Corion (Patriarch) on Oct 18, 2000 at 13:11 UTC

    The highly esteemed merlyn wrote something you could maybe use. I don't know if it will fit your exact problem, but his Highlander script restricts invocation to one instance by using a flocked sentinel file.

    While searching with the Super Search, I found out that it dosen't search the Code Catacombs - maybe that could be changed by The Powers That Be :-)

      thanks for the help, highlander seems to work perfectly. i appreciate all the help everyone offered so quickly. this place is the best.

      thanks again, steve
Re: Locking a script
by tilly (Archbishop) on Oct 18, 2000 at 14:36 UTC
    Try Simple Locking. It is pretty heavy with all of the writing it does, but it works.
Re: Locking a script
by ChOas (Curate) on Oct 18, 2000 at 13:13 UTC
    Eeehm what I would do is to set up a temporary file with
    a lock just before you enter your critical zone,
    (first check if it's not there already ofcourse ;)) just unlock/unlink the file when you're done

    Anyways, that's what I would do...
      You would have a serious race condition.

      Invocation 1 comes along, opens the file, and flocks it.

      Invocation 2 comes along, opens the file, and blocks on the flock.

      Invocation 1 leaves and unlinks the file, dropping the lock it had.

      Invocation 2 gets its lock on a temporary that only will exist until Invocation 2 is done.

      Invocation 3 comes along, sees no file, creates, flocks, and now Invocations 2 and 3 are running in parallel...

      (This is all with Unix filesystem semantics of course.)

        Okay, okay....

        Wasn't thinking heavy duty progamming for a sec. ;)))
        Dining Philosophers 'n stuff...

        How about a semaphore ?
        perldoc perlipc might give some clues...

(tye)Re: Locking a script
by tye (Sage) on Oct 18, 2000 at 21:38 UTC

    I just wanted to add that you could use the script itself as its own sentinel file. File locks in Perl are (usually) advisory so the lock will not prevent the script from running, for example. It will just prevent other instances of the script from getting the same lock.

            - tye (but my friends call me "Tye")
RE: Locking a script
by Penfold (Novice) on Oct 18, 2000 at 14:40 UTC
    If it is a 'short period of time', you don't want to lock the whole script, surely, just check whether a lockfile exists/is locked before you enter your critical regeion, and if it is, wait in some fashion for it to come free.
Re: Locking a script
by AgentM (Curate) on Oct 19, 2000 at 01:24 UTC
    Right. Most programs save a lock file in /var/run/X.pid where they actually save their PID. In their scripts, they first check for the existence of the file. If it doesn't exist, it is created, the PID is written to it and the file is locked and unlinked (an unlink is not able to take effect until the the last descriptor linked to that file is removed). The advantage of this is that it is much easier to find and stop a certain program without searching the process tables which are potentially very long). Also, if you start up a double of the script, it can offer optionally to kill or send any other various signal to the PID in the file as a quick form of IPC. If the process accidentally dies, the descriptor to the file is deleted, so the file can be unlinked. It's best to use such a "standard" way to manage larger apps like servers so that they cannot possibly interfere with each other.
    AgentM Systems nor Nasca Enterprises nor Bone::Easy is responsible for the comments made by AgentM.
Re: Locking a script
by d_i_r_t_y (Monk) on Oct 19, 2000 at 04:40 UTC
    i would definitely go for the 'traditional' unix method of creating a lock file somewhere local and then installing an exit handler to delete the lockfile before death.

    in pseudo-perl, this would be:

    if ( lockfile_exists() ) { warn script_is_locked(); exit 1; } $SIG{'__DIE__'} = \&remove_lockfile(); lock_file(); do_stuff(); remove_lockfile(); exit;

    just be sure to install your signal handler(s) after you test for file locking... race conditions really suck.

    dirty...

      That's not the traditional method, because the traditional methods work. {grin}

      You can't separate the steps of "test for a lockfile" from "create a lockfile". It has to be an "atomic" operation. See the massive literature on this.

      -- Randal L. Schwartz, Perl hacker

        Sure, it's called open(). I was just commenting on what is actually happening. To a newbie you just cutting out some code, it's not essential to know that this is an atomic kernel call.
        AgentM Systems nor Nasca Enterprises nor Bone::Easy is responsible for the comments made by AgentM.</h6>