For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > August 2005 > file locking question









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author file locking question
bob@yknet.ca

2005-08-28, 9:56 pm

I am upgrading a server from a very old version of redhat to a new
version of debian. One of the things that needs to come along to the
new server is a web based perl program consisting of about 50 files. I
seem to have the majority of it working, but I have hit a snag.
there are a number of lines that contain syntax like this:

$filelock = do lock ("user/$userid.lck");
and a few lines later;
do unlock ($filelock)

Not being familiar with perl, from logs, documentation,and googling, I
arrived at this;
if I change the lines like so, it works;

flock("user/$userid.lck",2);
and a few lines later;
flock("user/$userid.lck",8);

So I set about writing a sed script to make all the changes, but then I
started to realized the scope of doing this over so many files, where
each file's $filelock variable often refers to a different file, and a
number of other variables like $userlock and $messagelock, most file's
variable having different values as well. its to the point where its
faster to manually decipher and change each file in the perl program
than try to write a script to do it with any relaiability.
The perl version on the old box is 5.6, so perhaps syntax for that
version simply won't work with the current 5.8.7 I have now. but there
must be an easier way to go about this other than changing each file or
writing a massive script - maybe there is a module I am not familiar
with, or some other configuration option I can use to just make the
original syntax work. At this point I am now striking out on google, I
was wondering if one of you experts would point me to some
documentation on this matter, or perhaps offer some ideas about a
direction I could take on this

Gunnar Hjalmarsson

2005-08-29, 3:56 am

bob@yknet.ca wrote:
> I am upgrading a server from a very old version of redhat to a new
> version of debian. One of the things that needs to come along to the
> new server is a web based perl program consisting of about 50 files. I
> seem to have the majority of it working, but I have hit a snag.
> there are a number of lines that contain syntax like this:
>
> $filelock = do lock ("user/$userid.lck");
> and a few lines later;
> do unlock ($filelock)
>
> Not being familiar with perl, from logs, documentation,and googling, I
> arrived at this;
> if I change the lines like so, it works;
>
> flock("user/$userid.lck",2);
> and a few lines later;
> flock("user/$userid.lck",8);


How did you reach the conclusion that the original code does not work on
the newer OS? Doesn't the program define the lock() and unlock() functions?

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
xhoster@gmail.com

2005-08-29, 3:56 am

bob@yknet.ca wrote:
> I am upgrading a server from a very old version of redhat to a new
> version of debian. One of the things that needs to come along to the
> new server is a web based perl program consisting of about 50 files. I
> seem to have the majority of it working, but I have hit a snag.
> there are a number of lines that contain syntax like this:
>
> $filelock = do lock ("user/$userid.lck");
> and a few lines later;
> do unlock ($filelock)



And what is the problem with it? Is the "weak" keyword by the same name
(lock) getting in the way? Have you accidentally taken out the code that
defined the lock and unlock subroutines?


>
> Not being familiar with perl, from logs, documentation,and googling, I
> arrived at this;
> if I change the lines like so, it works;
>
> flock("user/$userid.lck",2);
> and a few lines later;
> flock("user/$userid.lck",8);


That doesn't work for me, I get "Bad file descriptor"

>
> So I set about writing a sed script to make all the changes, but then I
> started to realized the scope of doing this over so many files, where
> each file's $filelock variable often refers to a different file, and a
> number of other variables like $userlock and $messagelock, most file's
> variable having different values as well. its to the point where its
> faster to manually decipher and change each file in the perl program
> than try to write a script to do it with any relaiability.
> The perl version on the old box is 5.6, so perhaps syntax for that
> version simply won't work with the current 5.8.7 I have now. but there
> must be an easier way to go about this other than changing each file or
> writing a massive script - maybe there is a module I am not familiar
> with, or some other configuration option I can use to just make the
> original syntax work.


If you told us what was happening when you use this old syntax in your new
perl, I might be able to offer more help.


Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
bob@yknet.ca

2005-08-29, 3:56 am

Thank you both for your reply.
Valid questions,what I am doing and why I think its broken, I should
have included that at first, sorry...
first, let me say I am fairly certain I have apache and perl set up
properly, I arrive at that conclusion because by making the changes I
mentioned, I seem to be working, though I am quite discouraged doing
them all by hand.
The reason it was not working before is derived from information I
found in the apache2 error log, three entries, specifically:

[Sun Aug 28 11:26:00 2005] [error] [client 192.168.25.75] Can't modify
string in
lock at /var/www/computerisms/cgi-bin/ns/getpanel.pl line 21, near
""user/$PPid.lck
")", referer: http://192.168.25.200/
[Sun Aug 28 11:26:00 2005] [error] [client 192.168.25.75] Execution of
/var/www/
computerisms/cgi-bin/ns/getpanel.pl aborted due to compilation errors.,
referer: htt
p://192.168.25.200/
[Sun Aug 28 11:26:00 2005] [error] [client 192.168.25.75] Premature end
of scrip
t headers: getpanel.pl, referer: http://192.168.25.200/

In addition, the webpage comes up as internal server error and suggests
there will be answers in the logs.
the particular area of the file this error is talking about is here:

flock("user/$PPid.lck",2);
#$filelock = do lock ("user/$PPid.lck")

open (userfile, "<user/$PPid");
@userdata=<userfile>;
close (userfile);

foreach (@userdata)
{ if (substr ($_, -1) eq "\n") { chop; } };

flock("user/$PPid.lck",8);
#do unlock ($filelock)

when it comes to perl, I am no programmer, but my educated guess is
that the file needs to be locked while changes are made to it to
prevent more than one process from doing so at the same time. I tried
to find anything in google on "can't modify string in lock", and all
sorts of other things, and that led me to flock, and some experimenting
to what works.
But both of you seem to think I shouldn't be having this problem, or
perhaps I am approaching this from the wrong direction? any comments
appreciated :)


xhoster@gmail.com wrote:
> bob@yknet.ca wrote:
>
>
> And what is the problem with it? Is the "weak" keyword by the same name
> (lock) getting in the way? Have you accidentally taken out the code that
> defined the lock and unlock subroutines?
>
>
>
> That doesn't work for me, I get "Bad file descriptor"
>
>
> If you told us what was happening when you use this old syntax in your new
> perl, I might be able to offer more help.
>
>
> Xho
>
> --
> -------------------- http://NewsReader.Com/ --------------------
> Usenet Newsgroup Service $9.95/Month 30GB


John W. Krahn

2005-08-29, 3:56 am

bob@yknet.ca wrote:
>
> Valid questions,what I am doing and why I think its broken, I should
> have included that at first, sorry...
> first, let me say I am fairly certain I have apache and perl set up
> properly, I arrive at that conclusion because by making the changes I
> mentioned, I seem to be working, though I am quite discouraged doing
> them all by hand.
> The reason it was not working before is derived from information I
> found in the apache2 error log, three entries, specifically:
>
> [Sun Aug 28 11:26:00 2005] [error] [client 192.168.25.75] Can't modify
> string in
> lock at /var/www/computerisms/cgi-bin/ns/getpanel.pl line 21, near
> ""user/$PPid.lck
> ")", referer: http://192.168.25.200/


That error message (as well as all perl warning/error messages) is described
in the perldiag.pod file which should have been installed on your computer
when Perl was installed.

perldoc perldiag
[snip]
Can't modify %s in %s
(F) You aren't allowed to assign to the item indicated, or
otherwise try to change it, such as with an auto-increment.


> [Sun Aug 28 11:26:00 2005] [error] [client 192.168.25.75] Execution of
> /var/www/
> computerisms/cgi-bin/ns/getpanel.pl aborted due to compilation errors.,
> referer: htt
> p://192.168.25.200/
> [Sun Aug 28 11:26:00 2005] [error] [client 192.168.25.75] Premature end
> of scrip
> t headers: getpanel.pl, referer: http://192.168.25.200/
>
> In addition, the webpage comes up as internal server error and suggests
> there will be answers in the logs.
> the particular area of the file this error is talking about is here:
>
> flock("user/$PPid.lck",2);
> #$filelock = do lock ("user/$PPid.lck")
>
> open (userfile, "<user/$PPid");
> @userdata=<userfile>;
> close (userfile);
>
> foreach (@userdata)
> { if (substr ($_, -1) eq "\n") { chop; } };
>
> flock("user/$PPid.lck",8);
> #do unlock ($filelock)
>
> when it comes to perl, I am no programmer, but my educated guess is
> that the file needs to be locked while changes are made to it to
> prevent more than one process from doing so at the same time. I tried
> to find anything in google on "can't modify string in lock", and all
> sorts of other things, and that led me to flock, and some experimenting
> to what works.


Have a look at the "File Locking" section in the perlopentut.pod document, as
well, perlfaq5.pod has some information on file locking.

perldoc perlopentut
perldoc perlfaq5



John
--
use Perl;
program
fulfillment
bob@yknet.ca

2005-08-29, 6:59 pm

Thanks John:
I have had a quick cursory glance, and it looks again like I will have
to change all the "do lock"s to flocks, but I will read the full
documentation to make sure. thanks again :)

xhoster@gmail.com

2005-08-29, 6:59 pm

bob@yknet.ca wrote:
> Thank you both for your reply.
> Valid questions,what I am doing and why I think its broken, I should
> have included that at first, sorry...
> first, let me say I am fairly certain I have apache and perl set up
> properly, I arrive at that conclusion because by making the changes I
> mentioned, I seem to be working, though I am quite discouraged doing
> them all by hand.
> The reason it was not working before is derived from information I
> found in the apache2 error log, three entries, specifically:
>
> [Sun Aug 28 11:26:00 2005] [error] [client 192.168.25.75] Can't modify
> string in
> lock at /var/www/computerisms/cgi-bin/ns/getpanel.pl line 21, near
> ""user/$PPid.lck
> ")", referer: http://192.168.25.200/


It looks like you are getting hit by the relatively new keyword "lock",
which is used in threaded programs. It is a weak keyword, meaning that if
your program defines a subroutine named "lock" *before* your code tries to
call lock, then you it will call your subroutine. Otherwise, it calls the
built-in lock. I get the same error message when I call the built-in lock
with a string, they way you have.

Does your code define a lock subroutine? If so, is the subroutine defined
before your call to it?

Also, it seems that if you "use threads", then the built in "lock" always
gets called rather than your own lock routine.


> when it comes to perl, I am no programmer, but my educated guess is
> that the file needs to be locked while changes are made to it to
> prevent more than one process from doing so at the same time. I tried
> to find anything in google on "can't modify string in lock", and all
> sorts of other things, and that led me to flock, and some experimenting
> to what works.



This is a specific form of the generic "can't modify %s in %s".


> But both of you seem to think I shouldn't be having this problem, or
> perhaps I am approaching this from the wrong direction? any comments
> appreciated :)


Using the "do" form of the subroutine call is unnecessary. It should
be fairly simple to eliminate the "do" semi-automatically, as none of the
rest of the syntax changes.

There must be a definition of the lock and unlock subroutines somewhere in
the old code. Find them. Make sure that these subroutines are defined in
the new code. Make sure that they are defined early in the script (to
avoid getting bit by the new "lock" keyword.) Alternatively, rename your
"lock" subroutine definition and all uses of it to something else, like
"old_lock". This should be fairly easy to do in a semi-automated way, as
you don't need to muck with either the argument list or the return value.


Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
bob@yknet.ca

2005-08-30, 3:56 am

thanks for sticking with this Xho, Sending a beer or coffee or whatever
into the karma pool for you....
Ok, so you say:
"Does your code define a lock subroutine? If so, is the subroutine
defined
before your call to it?", so I get to looking around.
there is a file called unixlock.pl, its contents are such:

# semaphores for Unix

# apply semaphore
sub lock
{
local ($aword)=@_;
open (locklock, ">$aword");
flock (locklock, 2);
*locklock;
}

# release semaphore
sub unlock
{
local (*locklock) = @_;
close (locklock);
}

now I don't really understand what all the special characters here are
referring to, but sub lock, that has to be the lock subroutine. in the
config.pl file, I find a line called "do unixlock.pl", and in all
files, at the very top is the line, "do config.pl". the answer
therefore must be yes, I have the subroutine lock defined, and its
definition is defined before the script requires its use. If I
understand correctly, this is as it should be.
you offer the alternative:
"Alternatively, rename your
"lock" subroutine definition and all uses of it to something else, like

"old_lock". This should be fairly easy to do in a semi-automated way,
as
you don't need to muck with either the argument list or the return
value."

so if I understand this right, in unixlock.pl, I should take:
sub lock (and probably sub unlock)
and change it to sub old_lock (and probably sub unold_lock)
then, I should take from my various .pl files, the lines like:
$filelock = do lock ("user/$userid.lck"); and change it to $filelock =
do old_lock ("user/$userid.lck");
and thus replacing the keyword problem
wow, I think I understand this.... I have to try it...
no, that gets me:
[Mon Aug 29 21:26:24 2005] [error] [client 192.168.25.75] Undefined
subroutine &
main::oldlock called at /var/www/computerisms/cgi-bin/ns/getpanel.pl
line 21., refer
er: http://computerisms.ca/
Doh!
#sub lock
#sub old_lock
That won't work.

Voila :) uncomment that line, and I have joy!!!!
Xho, you are a genius! my many, many thanks...

A. Sinan Unur

2005-08-30, 7:56 am

Organization: Cornell University
Message-ID: <Xns96C23BD4D6B1Easu1cornelledu@127.0.0.1>
User-Agent: Xnews/??.01.30
Lines: 77
NNTP-Posting-Host: 6555ece1d56dcb1c3ac2f7a45ab69b6f
X-Complaints-To: abuse@worldnet.att.net
X-Trace: bgtnsc04-news.ops.worldnet.att.net 1125395573 6555ece1d56dcb1c3ac2f7a45ab69b6f (Tue, 30 Aug 2005 09:52:53 GMT)
NNTP-Posting-Date: Tue, 30 Aug 2005 09:52:53 GMT
Date: Tue, 30 Aug 2005 09:52:53 GMT
Xref: number1.nntp.dca.giganews.com comp.lang.perl.misc:580869

bob@yknet.ca wrote in news:1125377738.193585.214710
@f14g2000cwb.googlegroups.com:

> thanks for sticking with this Xho, Sending a beer or coffee or
> whatever into the karma pool for you....


[ Please quote some context when you reply ]


> Ok, so you say:
> "Does your code define a lock subroutine? If so, is the subroutine
> defined before your call to it?", so I get to looking around.
> there is a file called unixlock.pl, its contents are such:
>
> # semaphores for Unix


use Fcntl ':flock';

> # apply semaphore
> sub lock
> {
> local ($aword)=@_;


my ($lock_fn) = @_;

> open (locklock, ">$aword");


open my $lock_handle, '>', $lock_fn
or die "Cannot open $lock_fn: $!";

> flock (locklock, 2);


flock $lock_handle, LOCK_EX
or die "Cannot lock handle on $lock_fn: $!";

> *locklock;


return $lock)handle;

> }
>
> # release semaphore
> sub unlock
> {
> local (*locklock) = @_;


my $lock_handle = @_;

> close (locklock);


close $lock_handle
or die "Cannot close: $!";

> }
>
> now I don't really understand what all the special characters here are
> referring to, but sub lock, that has to be the lock subroutine. in
> the config.pl file, I find a line called "do unixlock.pl", and in all
> files, at the very top is the line, "do config.pl".


AFAIK, those happen at run time, not at compile time. I would put the
subroutines in their own module, and 'use' the module at the top of the
program, and call the subroutine's with their fully qualified package
name. Or, just change the names of the subroutines to, say, obtain_lock
and release_lock, respectively.

See also:

<URL:http://www.stonehenge.com/merlyn/We...ques/col54.html>

Sinan
--
A. Sinan Unur <1usa@llenroc.ude.invalid>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/c...guidelines.html
A. Sinan Unur

2005-08-30, 7:56 am

"A. Sinan Unur" <1usa@llenroc.ude.invalid> wrote in
news:Xns96C23BD4D6B1Easu1cornelledu@127.0.0.1:

> bob@yknet.ca wrote in news:1125377738.193585.214710
> @f14g2000cwb.googlegroups.com:
>

....

>
> my $lock_handle = @_;


Ooops!! That should have been:

my ($lock_handle) = @_;

--
A. Sinan Unur <1usa@llenroc.ude.invalid>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/c...guidelines.html
Anno Siegel

2005-08-30, 7:56 am

<xhoster@gmail.com> wrote in comp.lang.perl.misc:
> bob@yknet.ca wrote:


[...]

> avoid getting bit by the new "lock" keyword.) Alternatively, rename your
> "lock" subroutine definition and all uses of it to something else, like
> "old_lock".


Rename it to "do_lock", then s/do lock/do_lock/g; That's economy! :)

Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.
xhoster@gmail.com

2005-08-30, 6:58 pm

X-Trace: NewsReader.Com dV/ iCmnqaCL_w+@U9HPMEO998iL0N3tGZ7yoo1EYlnb
UllqeK/
Lines: 90
Xref: number1.nntp.dca.giganews.com comp.lang.perl.misc:580891

bob@yknet.ca wrote:
> thanks for sticking with this Xho, Sending a beer or coffee or whatever
> into the karma pool for you....


Thanks. <Homer Simpson> Coffee and Beer, Aaaarhhh </HS>

....
> # semaphores for Unix
>
> # apply semaphore
> sub lock
> {
> local ($aword)=@_;
> open (locklock, ">$aword");
> flock (locklock, 2);
> *locklock;
> }
>
> # release semaphore
> sub unlock
> {
> local (*locklock) = @_;
> close (locklock);
> }
>
> now I don't really understand what all the special characters here are
> referring to, but sub lock, that has to be the lock subroutine.


The * is for dealing with typeglobs. This is a hold over from the good/bad
old days before lexical file handles (or, more accurately, filehandles were
automatically held in lexical variables, or something like that) were
supported.

It should also do error checking, so a more modern version would be:

sub lock
{
my ($aword)=@_;
open (my $locklock, ">", $aword) or die "Can't upen $aword: $!";
flock ($locklock, 2) or die "Can't lock $aword: $!";
return $locklock;
}

And the "2" in the flock should rather be the constant from the
Fcntl module. Of all the big hairy problems I've run into with file
locking, none of them has ever traced back to using the integers rather
than the constants to specify the lock mode, but still it is good practice
(and probably good karma) and all.


> in the
> config.pl file, I find a line called "do unixlock.pl", and in all
> files, at the very top is the line, "do config.pl". the answer
> therefore must be yes, I have the subroutine lock defined, and its
> definition is defined before the script requires its use. If I
> understand correctly, this is as it should be.


I must confess I don't know why it doesn't work. I never "do" files, I
always "use" or "require" them.

> you offer the alternative:
> "Alternatively, rename your
> "lock" subroutine definition and all uses of it to something else, like
>
> "old_lock". This should be fairly easy to do in a semi-automated way,
> as
> you don't need to muck with either the argument list or the return
> value."
>
> so if I understand this right, in unixlock.pl, I should take:
> sub lock (and probably sub unlock)
> and change it to sub old_lock (and probably sub unold_lock)
> then, I should take from my various .pl files, the lines like:
> $filelock = do lock ("user/$userid.lck"); and change it to $filelock =
> do old_lock ("user/$userid.lck");
> and thus replacing the keyword problem


You should also take out the "do" while you are at it, as it has been
deprecated for a long time. Who knows what problem that little word will
cause the *next* time you upgrade!

....

You're welcome.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com