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

I have a file that is being used to lock a process that contains only the values of 1 and 0 in it. I have tried opening the File and $value = <file_name> as well as foreach(<file_name>){$value = $_}. I do not only want to `cat $file_name` because if the file is unreadable I want to be able to trap the error. What are my alternatives? I need to be able to do the following but for some reason it is not working...

STAGE_DIM: if(not(open(process_lock, "+>$proc_lock"))){ goto STAGE_DIM; sleep 1; } $lock_val = <process_lock>; #`cat $proc_lock`; print "Value=*$lock_val*\n"; if( $lock_val == 1) { close(process_lock); sleep 1; goto STAGE_DIM; } else { ... }

The Value read is always "". The only way thus far, I have been able to read the contents of the file was to $lock_val = `cat $proc_lock`; but this leaves the chance that the file could be unreadable because another Process has it locked open. Any ideas would be appreciated. Thanks. rheaton

Replies are listed 'Best First'.
Re: File Read
by Fletch (Bishop) on Mar 12, 2007 at 13:06 UTC

    A file mode of "+>" will clobber the contents (if any) of the file you open that way (see perlopentut), which would explain why it's always empty.

      I understand that this will Truncate the file but should it be truncating it when it is opened? I want it to truncate on write of data. Is there something different that I need to do to make that work? I inadvertantly left out of the code supplied previously that in the else I printf file_name "1"; to lock the file if it wasnt locked. So another Process cannot access it while This one is using it. I am essentially serializing a Parallel Process with these locks because it has to be due to database and workfile access.

        My question becomes... How can I Open a file once, read the contents of the file then Truncate these contents to another value and then close the file?

Re: File Read
by derby (Abbot) on Mar 12, 2007 at 14:48 UTC

      I am not attempting to lock the file... I am locking a parallel process from executing one section from running in Parallel and forcing it to run in serial. In order to do that I needed to store a flag in a file that can be accessed by multiple running processesshowing whether a process is executing that section or not. Looping the other Processes until that section is free to run. Then the next process will lock the section and process and release the lock when finished. Thanks for everyone's help though. I found that I was able to use file access +>> and the truncate function to achieve what I needed.

        The problem is you do need some sort of atomic locking. There's nothing preventing both your processes from simultaneously obtaining "not locked" results from the file.

        • Process A opens and reads the unlocked status
        • Process A gets put to sleep
        • Process B starts running
        • Process B opens and reads the unlocked status
        • B writes the locked status into the file and gets put to sleep
        • A writes the locked status into the file and starts on its way
        • B wakes up and hilarity ensues!
        I am not attempting to lock the file... I am locking a parallel process ...

        Right. What people are tying to tell you is, you should use file locking to do that. Holding state in a file without locking is inherently subject to race conditions. Instead of using the file content (0/1) to indicate a critical region in your process(es), lock a file (exclusively) and use the lock status directly. Locking is meant to do process serialization free of race conditions, if used correctly.

        The file content is irrelevant, though your situation it may be useful to write the PID to the file when a process gets a lock.

        Anno

Re: File Read
by MonkE (Hermit) on Mar 12, 2007 at 13:45 UTC
    Try using "+>>" in your open statement. If I understood you correctly, it will do what you want: mix reads and writes on the same file handle.

      The >> operator is the Append operator. I want to Read the Files contents. Depending on those contents (if contents = 0) then Truncate and write "1". I do not want to close the file and reopen it with a different operator as that will allow for the file to be opened by another process. There needs to be a way to open a file Read/Write, to Read the Data and then when writing to the file Truncate the data and write a value out.