in reply to CGI Form processing

The basic steps are as follows:

The reason for the lockfile is simple: you can't flock a file until it's opened, but by then something else might already have opened that file and done something to it. Two programs trying to access your log at the same time (say, one for reading and one for writing) could cause data corruption or a race condition. By using a lock file, you have a file that can safely be opened and flocked without worrying about whether or not it's going to get corrupted.

#!/usr/bin/perl -wT use strict; use Fcntl qw/:flock/; use CGI qw/:standard/; my $log = 'somelog.log'; my $lockfile = "$log.lock"; # grab form data my $_name = param( 'name' ); my $_email = param( 'email' ); # untaint form data my ( $name ) = ( $_name =~ /^([\w.',]{1,30})$/ ) or some_error_routine( $_name ); # I *hate* dot-star untainting, but virtually any character # is valid in an email address. my ( $email ) = ( $_email =~ /^(.{1,500})$/ ) or some_error_routine( $_name ); # We're getting rid of ASCII zero as this is the delimiter # in the file we're writing to. $email =~ s/\0//g; open LOCK, "> $lockfile" or die "Cannot open $lockfile: $!"; flock LOCK, LOCK_EX or die "Cannot flock $lockfile: $!"; open LOG, ">> $log" or die "Can't open $log for appending: $!"; print LOG "$name\0$email\n"; close LOG; close LOCK; # output some response here

Note that the above code is incomplete and untested. Further, I have limited the length of the $name and $email variables. This is done to ensure that someone doesn't try to enter unreasonably large values for this data.

Cheers,
Ovid

Vote for paco!

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Replies are listed 'Best First'.
Re (tilly) 2: CGI Form processing
by tilly (Archbishop) on Jun 29, 2001 at 20:19 UTC
    If all programs are going to read or write the log, then there is no need for the lockfile. Everything can flock the log directly.

    There are two good reasons to use a lockfile. The first is that you may have operations involving multiple data sources and you want to maintain sync. The second is that you are both reading and writing to the same file and you want to avoid race conditions due to dropping the lock. But if everything is either just reading or just writing, then there is no race to worry about.

    Also one warning on lockfiles. If you want to get atomic behaviour (if you don't know what that is then let your eyes glaze over and say "Yes") then you do not want to delete the lockfile. Else 2 processes can go to create it at once, one creates, the other overwrites with its new, both have filehandles to different files. (One is temporary.) The flocks both are captured at once, both think they have the lock. The timing has to be reasonably precise to do this, but it is worth knowing about.

Re: (Ovid) Re: CGI Form processing
by merlyn (Sage) on Jun 29, 2001 at 18:02 UTC
    If you're sure that the data you're appending is under BUFSIZ chars (like 8192 on most modern Unix systems), you can use syswrite and avoid the flock, because append-writes are atomic. Saves a few steps, anyway.

    -- Randal L. Schwartz, Perl hacker

      As I recall, if you use syswrite, then the value of BUFSIZ doesn't matter. BUFSIZ matters if you allow buffering or if you are using pipes.

              - tye (but my friends call me "Tye")
        Ahh, I was mixing up what happens with FIFOs (pipes). Only BUFSIZ bytes on a FIFO are guaranteed to be atomically readable.

        Thanks for clarification.

        -- Randal L. Schwartz, Perl hacker

Re: (Ovid) Re: CGI Form processing
by Anonymous Monk on Jun 29, 2001 at 01:23 UTC
    Thank you very much!