can you flock a file or lock a file before opening it.

J

John Smith

I want to ensure that only one person at a time can edit a file using my
perl script.

From what I've read, it appears that you can only flock a file after opening
it.
So I guess it would look like this:

- open the file for writing
- flock the file for exclusive (2)
- update the file
- unflock the file or flock (8)
- close the file

I'm suspecting that if the file is already open when you try to flock it,
the flock function will return an error code?


Now this would work great if you are trying to append to a file, as in a log
file, but what if you want to change info in the file? Maybe I'm not doing
this properly.

- My program opens (for read), reads the entire file, and closes the file.
- Then it open (for write), re-writes the complete file (with the updates),
and closes the file.


From what I understand, if I can't lock the file before opening it, then
this flock won't help me.


Now it turns out that my perl script will be the only program accessing
these files.
So I thought, that maybe I could have a dummy file that I would flock. If I
can flock this file, then I would allow my perl program to read, delete,
re-write or whatever to my other data files. Once I'm done, I unflock the
dummy file.


Another question... My perl script runs on a web server and when it is
called, it does a few quick things and terminates. When the perl script
terminates, will all files locked by the perl script be unlocked upon
termination (in the event that an error occured and it ended prematurely -
not that it would).


I think I was told that the web server is running perl 5.8???
This brings me to a final question.
Is there a function that can retrieve the version of Perl that is running?
This would be nice since the server is like 3 hours away (200 miles away!)


Thanks for all.
G.Doucet
 
W

William Herrera

I want to ensure that only one person at a time can edit a file using my
perl script.

From what I've read, it appears that you can only flock a file after opening
it.
So I guess it would look like this:

- open the file for writing
- flock the file for exclusive (2)
- update the file
- unflock the file or flock (8)
- close the file

I'm suspecting that if the file is already open when you try to flock it,
the flock function will return an error code?

If the file is already locked, the program will either wait for the lock to be
released or will return an error. This depends on the second argument to flock.
See the docs in perlfunc:
===
OPERATION is one of LOCK_SH, LOCK_EX, or LOCK_UN, possibly combined with
LOCK_NB. These constants are traditionally valued 1, 2, 8 and 4, but you can
use the symbolic names if you import them from the Fcntl module, either
individually, or as a group using the ':flock' tag. LOCK_SH requests a shared
lock, LOCK_EX requests an exclusive lock, and LOCK_UN releases a previously
requested lock. If LOCK_NB is bitwise-or'ed with LOCK_SH or LOCK_EX then flock
will return immediately rather than blocking waiting for the lock (check the
return status to see if you got it).
===
So I thought, that maybe I could have a dummy file that I would flock. If I
can flock this file, then I would allow my perl program to read, delete,
re-write or whatever to my other data files. Once I'm done, I unflock the
dummy file.

I use this in one script that writes its log entries to a db file (don't ask
why :)). Here's a code excerpt:

dblogflock();
tie(%lastogin, 'DB_File', $login_db) or mydie('Cannot tie login DB',
__LINE__);
$lastlogin{$user} = time;
untie %logins;
undblogflock();

sub dblogflock {
open(LDBM, ">$loglockfile") or mydie("loglockfile error: $!", __LINE__);
flock LDBM, 2;
}

sub undblogflock {
close LDBM;
}

Note that this will wait until the other process releases the lock before it
completes.
 
B

Brian McCauley

[ Unless you have permission from Microsoft to use their domain in
your mail address then doing so is rude to say the least (and probably
actionable). ]
I want to ensure that only one person at a time can edit a file using my
perl script.

From what I've read, it appears that you can only flock a file after opening
it.
So I guess it would look like this:

- open the file for writing
- flock the file for exclusive (2)
- update the file
- unflock the file or flock (8)
- close the file

I'm suspecting that if the file is already open when you try to flock it,
the flock function will return an error code?

Just being open will not interact with locking unless you have
mandatory locking configured on the file at the OS level.

flock() will block rather than return a failure code unless to
explicitly ask for non-blocking mode.
- My program opens (for read), reads the entire file, and closes the file.
- Then it open (for write), re-writes the complete file (with the updates),
and closes the file.

From what I understand, if I can't lock the file before opening it, then
this flock won't help me.

So open the file read/write in the first place then you don't need to
close it and can hold the lock throughout.
So I thought, that maybe I could have a dummy file that I would flock. If I
can flock this file, then I would allow my perl program to read, delete,
re-write or whatever to my other data files. Once I'm done, I unflock the
dummy file.

That too, is a valid approach.

Be aware that to cope gracefully with abnormal termination one usually
would write the updated file to a new file then rename that file over
the old one. This trick would need to combined with the
aforementioned "separate lockfile" approach on OSs that lack an atomic
rename-over-existing-file.

To save re-inventing the wheel, see the module IO::AtomicFile on CPAN.
Another question...
Errr....

My perl script runs on a web server and when it is called, it does a
few quick things and terminates. When the perl script terminates,
will all files locked by the perl script be unlocked upon
termination (in the event that an error occured and it ended
prematurely - not that it would).

[ Er, what was your question? I shall assume "It is true that ...?"]

Under CGI yes, the above is true, because a CGI script runs as a
separate process. When the process terminates all resources held by
it are (or at least should be) freed by the OS.

This is not necessarily the case under other mechanisms that may be
used to connect your Perl script to the web server (mod_perl, FastCGI,
whatever).

Using a bare filehandle you can avoid this thus:

local *FOO;
open FOO, '<+', $filename or die "Can't open $filename: $!";

This will close the file on exiting the current lexical scope, whether
normally or abnormally.

However, I suggest that people should always open files using
filehandle references rather than bare filehandles except when
backward compatability with old versions of Perl is needed. (And if
you are using IO::AtomicFile you'd be using a reference anyhow).

open my $foo, '<+', $filename or die "Can't open $filename: $!";

This will close the file upon destruction of the last copy of the
reference held in $foo. This will close the file upon termination so
long as your program hasn't leaked any copies of the reference in
$foo.

Note that under mod_perl's Registry you can't declare $foo as a
lexical variable at the file-scope an then use $foo within a
subroutine.

A workround for the latter is to use a package variable and local().

open local our $foo, '<+', $filename or die "Can't open $filename: $!";
I think I was told that the web server is running perl 5.8???
This brings me to a final question.
Is there a function that can retrieve the version of Perl that is running?
This would be nice since the server is like 3 hours away (200 miles away!)

$]

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top