Re: Perl script crashing at lockfile ?
by tachyon (Chancellor) on Oct 01, 2003 at 12:03 UTC
|
lockfile can be used to create one or more semaphore
files. If lockfile can't create all the specified files
(in the specified order), it waits sleeptime (defaults to
8) seconds and retries the last file that didn't succeed.
You can specify the number of retries to do until failure
is returned. If the number of retries is -1 (default,
i.e., -r-1) lockfile will retry forever.
So it is not able to create the file and it retries forever. Actually you are setting -2 as the retry interval and trying to set a max of 5 retries so it sould return after 10 seconds but it is not. GOK. Why shell out to create lockfiles anyway? Why not just do it native say like
sysopen($fh, "$dir/$name", O_CREAT | O_EXCL | O_RDWR, 0600);
cheers
tachyon
s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print
| [reply] [d/l] [select] |
|
|
sysopen($fh, "$dir/$name", O_CREAT | O_EXCL | O_RDWR, 0600);
Thanks for supplying the code. I don't know why the person wanted to lock the file. Here is a bigger snippet of what is happening, down to the unlink, which I think is like the "unlock" ??
system ("lockfile -2 -r 5 $base_dir/.lock") == 0
or diehtml("Lock error: ", $? >> 8, "\n");
# TODO stop stderr of system
# create unique suffix
if (-f "$base_dir/$seq_file") {
open(SEQ, "+<$base_dir/$seq_file")
or diehtml("Error opening seq file: $!\n");
$seq = ;
seek SEQ, 0, 0;
} else {
open(SEQ, ">$base_dir/$seq_file")
or diehtml("Error creating seq file: $!\n");
$seq = 0;
}
$outfile .= sprintf "%7.7d", $seq;
$ordernumber = $seq; #store this order no. before 'next' is cal
+c.
print SEQ ++$seq;
close SEQ or warn "Something wrong closing seq: $!\n";
unlink "$base_dir/.lock" or diehtml("Unlock error: $!\n");
open(ORDERFILE, ">$outfile")
or diehtml("Can't open order records: $!\n");
print ORDERFILE @_;
close ORDERFILE or warn "Something fishy with closing the order: $
+!\n";
}
The file SEQ, is just a line line ASCII file with the next order number in it.
Peter
| [reply] [d/l] [select] |
|
|
I didn't write it, and I don't know Perl very well at all.
We know. Regardless you have come to the right place for help.
The purpose of a lockfile is to tell other processes (ie copies of a CGI) to bugger off and wait their turn. Anyway here is a pure Perl replacement that is identical to the lockfile call (well it is not IDENTICAL) because this actually works as the system call to lockfile should....
my $got_lock;
use Fcntl; # to get constants for O_CREAT | O_EXCL | O_RDWR
for ( 0 .. 5 ) {
if ( sysopen(my $fh, "$base_dir/.lock", O_CREAT | O_EXCL | O_RDWR,
+ 0600) ) {
$got_lock = 1;
close $fh;
last;
}
sleep 2;
}
diehtml("Lock error $!\n") unless $got_lock;
That should be a cut and paste replacement for this:
system ("lockfile -2 -r 5 $base_dir/.lock") == 0
or diehtml("Lock error: ", $? >> 8, "\n");
# TODO stop stderr of system
cheers
tachyon
s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
enter program
while (1)
look for lockfile
if lockfile does not exist exit
sleep 5 seconds
}
create lockfile
..... do normal program stuff ......
unlink lockfile
exit
However, if the process died before removing the lock, it crashed the web server. The post was 7 years ago, so no doubt what has been suggested here will be _much_ better. :)
Peter
| [reply] [d/l] |
|
|
>>Suggestion. SSH into the shell and deal with your server like a (man/woman/real hacker).
Okay, I will have to leave it until the morning, it's late here (down under), and the pwd for SSH access is on another computer.
Possibly the code needs rewriting anyway. Thanks to you all for your help, ... wow, I have never received such fast responses. :)
Peter
| [reply] |
|
|
my $got_lock;
use Fcntl; # to get constants for O_CREAT | O_EXCL | O_RDWR
for ( 0 .. 5 ) {
if ( sysopen(my $fh, "$base_dir/.lock", O_CREAT | O_EXCL | O_RDWR,
+ 0600) ) {
$got_lock = 1;
close $fh;
last;
}
sleep 2;
}
diehtml("Lock error $!\n") unless $got_lock;
.. or the "fully blown" lockfile code you supplied in your other post ..You either have to delete it by hand or do something like this:
I consider the lockfile problem sorted out now, thanks. Because of the problems now with "opens", I would to replace code like this:
open(ORDERFILE, ">$outfile")
or diehtml("Can't open order records: $!\n");
with (native) code of the format:
sysopen($fh, "$dir/$name", O_CREAT | O_EXCL | O_RDWR, 0600);
... would it be something like:
$fh = "ORDERFILE";
sysopen($fh, "$outfile", O_CREAT | O_EXCL | O_RDWR, 0600)
or diehtml("Can't open order records: $!\n");
Just a wild guess. :)
Peter
| [reply] [d/l] [select] |
|
|
open # open a file for read or write
(
ORDERFILE # onto a FILEHANDLE called ORDERFILE
,
"
> # > means write to the file, create if does not exist
# Note all previous content will be deleted
# if this file exists >> means append to the end
$outfile # full or relative path to file
"
)
or # if the open works it returns true so we never do the next
+ bit
diehtml() # print an error message
You don't wanna touch anything in the demon code. It was for illustrative purposes and is not relevant to your problem provided you are happy that the code you have worked just replace the lockfile code.
In this code:
$fh = "ORDERFILE";
sysopen($fh, "$outfile", O_CREAT | O_EXCL | O_RDWR, 0600)
or diehtml("Can't open order records: $!\n");
You don't need to set $fh to a string. It will just get overwritten in the open. A FILEHANDLE is a type of perl internal object (like a scalar) and the reference to it is held in the $fh var. To illustrate the syntax:
open $fh, ">$file" or die "Can't write $file $!\n";
print $fh "here is some data\n";
close $fh;
Same with sysopen but I can't be bothered to type that much.
cheers
tachyon
s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print
| [reply] [d/l] [select] |
Re: Perl script crashing at lockfile ?
by robartes (Priest) on Oct 01, 2003 at 12:00 UTC
|
If by 'stopping' you mean 'just sitting there and doing nothing usefull' (as opposed to 'exiting'), than have a look at the man page for lockfile on your system. The system function does not return until the spawned program, lockfile in this case, returns.
If your system call is not returning, that means the lockfile process is not returning. Take a look at that.
File locking is a tricky field that is very susceptible to portability issues. You might have been bitten by one of them.
| [reply] [d/l] [select] |
|
|
Hi,
Yikes, .. I just used CPanel to check on the installed Perl modules, and I couldn't find lockfile or system, so I guess I'm going to have to change the code.
Thanks,
Peter
| [reply] [d/l] [select] |
|
|
Whoa, hang on there.
system is a perl built-in function, so you do not need any modules installed to have it available.
lockfile is part of your operating system software (well, that's not technically completely accurate, but close enough), so it has nothing to do with Perl in itself.
Back out of that alley you've gone down and look for the solution in another direction :). Your problem is most probably situated in different behaviour of lockfile between your original and current systems.
| [reply] [d/l] [select] |
|
|
|
|
lockfile(1) is part of the OS. system() is part of Perl. Neither are Perl modules. Regardless of your lack of understanding of what your code is doing to what and where your analysis of the required actions is correct.
Suggestion. SSH into the shell and deal with your server like a (man/woman/real hacker).
cheers
tachyon
s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print
| [reply] |
Re: Perl script crashing at lockfile ?
by hardburn (Abbot) on Oct 01, 2003 at 14:13 UTC
|
You're running under taint mode and don't appear to be setting $ENV{PATH}. You can't execute external programs under taint without setting the PATH env var. Better still is to write the lockfile code in pure Perl.
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
Note: All code is untested, unless otherwise stated
| [reply] [d/l] [select] |
|
|
You're running under taint mode and don't appear to be setting $ENV{PATH}. You can't execute external programs under taint without setting the PATH env var.
How do I set $ENV{PATH} , and what should I set it to ?
Better still is to write the lockfile code in pure Perl.
The lockfile part of the code is now in pure Perl
Thanks,
Peter
| [reply] |
|
|
| [reply] [d/l] |
Re: Perl script crashing at lockfile ?
by peterr (Scribe) on Oct 02, 2003 at 03:37 UTC
|
Hi,
With replacing the code, the script is getting further now. It is stopping or just sitting at the following block of code
open(ORDERFILE, ">$outfile")
or diehtml("Can't open order records: $!\n");
print ORDERFILE @_;
close ORDERFILE or warn "Something fishy with closing the order: $
+!\n";
The value of the variable $outfile has been printed before the above code, and is "/home/username/public_html/.orders/2003-10-01-0001130"
There were other "open" commands performed successfully, prior to _this_ open stopping ?
Peter
| [reply] [d/l] |
|
|
Should I replace the following with a 'sysopen' function, like in the locking example ?
open(ORDERFILE, ">$outfile")
Peter
| [reply] [d/l] |
|
|
Hi,
Well, that worked, it has now actually created the ascii order file, and gone much further. Now it is stopping/doing nothing here
open(SENDMAIL, '|/usr/sbin/sendmail -oi -t')
or (unlink ($outfile),
diehtml("Can't fork for sendmail: $!\n"));
So, .... it looks like the moral to this story is replace ALL open() with sysopen(), using the parameters and examples as supplied, to fix the locking example.
If I used this code as a template for all the file opens
my $got_lock;
use Fcntl; # to get constants for O_CREAT | O_EXCL | O_RDWR
for ( 0 .. 5 ) {
if ( sysopen(my $fh, "$base_dir/.lock", O_CREAT | O_EXCL | O_RDWR,
+ 0600) ) {
$got_lock = 1;
close $fh;
last;
}
sleep 2;
}
diehtml("Lock error $!\n") unless $got_lock;
.... would I need the 'sleep', and what does the FOR contruct do ? Does it try for 6 times ?? Please pardon my ignorance, I'm _very_ much a novice at Perl. :)
Thanks,
Peter
| [reply] [d/l] [select] |
|
|
|
|