file open - read -write problem

I'd like to open file, read file , modify file, rewrite file and then close file.
It is done like this:

if(open(FILE_USERS,"<FILE_USERS"))
{@fileUsers=<FILE_USERS>;
 modifyFile(@fileUsers);
 if(open(FILE_USERS,">FILE_USERS"))
  {print FILE_USERS "$NewFileContent";}
 close(FILE_USERS);
}

This works fine, but when 2 users connect almost simultaneously the problem arise in that way:

1) User 1 reads file
2) User 2 reads file (not supposed until User 2 finish with the file)
3) User 1 modify file
4) User 2 modify file
5) User 1 rerecords and close file
6) User 2 rerecords and close file

So actually User 2 doesn't see modification made to file by user 1 becouse he reads file before it recorded by user 1. And all modification made by user 1 is lost.

Is there any way prevent user 2 read and modify file until User 1 (who opened file first) finished?
LVL 2
serg111Asked:
Who is Participating?
 
RobWMartinConnect With a Mentor Commented:
Odd that it is stuck like that.  However, to break the lock, you just need to unlink the file.  As root,

cp thefile{,.bak}
rm thefile
cp thefile{.bak,}

Rob
0
 
RobWMartinCommented:
If you are on an O/S that supports flock, you can use it, as follows:

if(open(FILE_USERS,"<FILE_USERS"))
{
 flock(FILE_USERS,LOCK_EX);
 @fileUsers=<FILE_USERS>;
 modifyFile(@fileUsers);
 if(open(FILE_USERS,">FILE_USERS"))
  {print FILE_USERS "$NewFileContent";}
 close(FILE_USERS);
 flock(FILE_USERS,LOCK_UN);
}

This works as long as both users are accessing the file through the same script.  I.e. both have to attempt the flock.

Rob

0
 
guadalupeCommented:
Use the perl flock() command:

flock(FILEHANDLE, 1) #To lock

flock(FILEHANDLE, 0) #To unlock
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
RobWMartinCommented:
BTW: you can read the details in perlfunc, i.e.:

perldoc -f flock

The second argument specifies the type of lock, or action.  Thus, LOCK_EX says lock the filehandle exclusively (i.e. no one else can access it, will it is locked); the LOCK_UN says unlock the filehandle.  This is a blocking lock, so if the flock never gets a lock for whatever reason it will continue waiting indefinitely.

0
 
serg111Author Commented:
It looks like flock() doesn't work:
I tested following code

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_CLIENTS1, 2);
open(FILE_USERS2,">>$filePath");
$iRet=flock(FILE_CLIENTS1, 8);

Both flock returns 1
and both open() successfully opened file.

Regards
0
 
serg111Author Commented:
Sorry there is misspelling in code it should look like h

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_USERS1, 2);
open(FILE_USERS2,">>$filePath");
$iRet=flock(FILE_USERS1, 8);

0
 
ozoCommented:
Did you open FILE_CLIENTS1?
0
 
serg111Author Commented:
in both cases open() return 1

Thanks
0
 
RobWMartinCommented:
You misunderstand the purpose of flock.  It will block indefinitely if called the second time with LOCK_EX (i.e. 2), waiting for someone to unlock the file.  It is an advisory lock, not a real file-system lock.  So, before you try to open a file that might have multiple processes access it, you try to lock it first with flock.  If some other, cooperating, process has a valid flock on the file, your flock will sit and wait.  When it returns, then you are safe to go on and open the file.  Thus, if you try the following, your script will hang:

$iRet=flock(FILE_CLIENTS1, 2);               #  2 (LOCK_EX) here
open(FILE_USERS1,"<$filePath");


$iRet=flock(FILE_CLIENTS1, 2);               #  2 (LOCK_EX) here, also.
open(FILE_USERS2,">>$filePath");

The second will block forever.  It is protecting the file like it should.

Hope this clarifies it for you.

Rob
0
 
RobWMartinCommented:
Well, if I could get it in the right order, it would help:

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_CLIENTS1, 2);               #  2 (LOCK_EX) here


open(FILE_USERS2,">>$filePath");
$iRet=flock(FILE_CLIENTS2, 2);               #  2 (LOCK_EX) here, also.
 

In other words, you may open successfully, but don't mess with it until you get a successful lock.

Rob
0
 
serg111Author Commented:
OK.
I have tested this code

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_CLIENTS1, 2);
open(FILE_USERS2,"<<$filePath");
$iRet=flock(FILE_CLIENTS2, 2);  

For first time it worked fine (first flock() return 1 and second doesn't return.
But when I call script now first flock() doesn't return. So it looks like it is locked forever. When I added $iRet=flock(FILE_CLIENTS2, 8) it does not help. Is there any way to remove the lock?

0
 
WhittyCommented:
You should use flock() as follows:

open(FILE_USERS1,"<$filePath");
$retVal=flock(FILE_CLIENTS1, 2);               #  Performs and exclusive lock
# Process file as needed
$retVal=flock(FILE_CLIENTS1, 8);               #  Removes the lock
close(FILE_CLIENTS1);

Although the file is automatically "unlocked" when closed, it is a good idea to manually perform the unlock just to be safe.

Now if the same application is called again, for say the second user, the flock() for the second user will wait until any existing locks are released.

For info, see the Perl Cookbook, pg. 245.

Hope this helps...

Whitty

                       
0
 
RobWMartinCommented:
Just realized I cut and pasted the wrong code.  The FILEHANDLES don't match up.  

open(FILE_USERS1,"<$filePath");
$iRet=flock(FILE_USERS1, 2);               #  2 (LOCK_EX) here


open(FILE_USERS2,">>$filePath");
$iRet=flock(FILE_USERS2, 2);               #  2 (LOCK_EX) here, also.


 

0
 
serg111Author Commented:
More:

This code works fine with other files. I'm quite happy with it, but I still have prblem with one file "clients/M" where this code is not working.
I tested this file first and probably it remains locked.

Any ideas please
0
 
WhittyCommented:
Are you implementing an unlock call?

flock(FILE_CLIENTS1, 8);               #  Removes the lock

Whitty
0
 
RobWMartinCommented:
Don't think that works if some other (rampaging) process has it locked.  If I understand serg111's (current) problem, it's that one of his initial tests with locking still has the file locked somehow(?????)  Requires intervention outside the flock function.

Rob
0
 
WhittyCommented:
If that is the case, killing the rampaging process would terminate the lock.  Perl's built-in cleanup would handle this by closing any open file handles.  When a file is closed, the lock is automatically terminated (it's just good practice to do it manually prior to the close).

Whitty
0
 
RobWMartinCommented:
Agreed, but the file removal method above doesn't require serg111 to look for the rampaging process.  I'm still not certain how the file can still be locked.  Unless, serg111 is in bash and did ^Z vs ^C.

????

Rob
0
 
WhittyCommented:
Good point.  Since serg111 hasn't responded to any of our comments for a while, I assume everything is working now?!?

Whitty
0
All Courses

From novice to tech pro — start learning today.