in reply to Perl script crashing at lockfile ?

System is a blocking call. Here is the begining of the man page for lockfile. Does that help?

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

Replies are listed 'Best First'.
Re: Re: Perl script crashing at lockfile ?
by peterr (Scribe) on Oct 01, 2003 at 12:27 UTC
    >>Why shell out to create lockfiles anyway?

    I didn't write it, and I don't know Perl very well at all.

    >>Why not just do it native say like

    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

      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

        Is there a line vaguely like:
        while (-e "$base_dir/.lock") { sleep 1; }

        just above the code you have shown us????

        Definitely not, no 'while' or 'sleep' code. It's all drop down, except for a few subs.

        Thanks for supplying the pure Perl replacement code, I'll try that today. Would I still leave this line the same ?

        unlink "$base_dir/.lock" or diehtml("Unlock error: $!\n");

        Thanks a lot,

        Peter

      I don't know why the person wanted to lock the file.

      I actually found a post on comp.lang.perl.misc that was from the guy that wrote it; here is his algorithm:

      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

Re: Re: Perl script crashing at lockfile ?
by peterr (Scribe) on Oct 01, 2003 at 12:38 UTC
    >>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

Re: Re: Perl script crashing at lockfile ?
by peterr (Scribe) on Oct 02, 2003 at 11:12 UTC
    Hi tachyon,

    Thanks for sorting out the lockfile problem. I will either use this one you supplied

    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

      No :-)

      This code is fine for what it does:

      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