in reply to Avoiding race conditions

I have a calendaring system which I tinker with from time to time and I make PDF reports of schedules and such. What I did was make the text into a POD format, then use POD::Pdf (well, a hacked up version). But, that may not fit your needs :) I have used some other PDF tooks in the past and suggest trying a few to see what is best for your app.

As for the filenames. Is the 'user' actually logged in (via some way you have an equiv of REMOTE_USER)? I have used things like $ENV{REMOTE_USER}.$$.file.ext for simple anti-race names. I also use the following to generate a random name:

my @set = ('a' .. 'z', 'A' .. 'Z'); my $length = 8; # Change length if desired my $random = join "" => map {$set [rand @set]} 1 .. $length; my $tmp_file = $random . "." . $$ . ".ext";

Many people have their own way to get a unique name. I tend to like adding a login name (if available), the PID (assuming I will unlink() the file when done), and some random string. If you are extra paranoid (or extra careful :) you could also add a sempahore file with the name of your temp file, and lock it. If you can't get a lock on it, then the name must be in use and you can generate another.

Cheers,
KM

Replies are listed 'Best First'.
Re: Re: Avoiding race conditions
by swiftone (Curate) on Apr 24, 2001 at 21:03 UTC
    POD::Pdf:
    My data is in two column table format, so I don't think POD will pull it off, but I'll give it a glance anyway. Does POD support pagebreaks?

    Unique features:
    No, sadly the user is not logged in. This isn't mod_perl, just straight CGI, so I could use the PID I suppose. hmm. Other than a cronjob, I have no idea how to automatically unlink the file, since the CGI creating the PDF will end presumably long before the PDF is completely downloaded.
      My data is in two column table format, so I don't think POD will pull it off, but I'll give it a glance anyway. Does POD support pagebreaks?

      Yeah, I would experiment with other POD::*, or a *2pdf utility. POD doesn't do pagebreaks (as far as I have ever read), but the PDF module/utility will give you a way to define the page dimensions.. so it should add pagebreaks.

      No, sadly the user is not logged in. This isn't mod_perl, just straight CGI, so I could use the PID I suppose. hmm. Other than a cronjob, I have no idea how to automatically unlink the file, since the CGI creating the PDF will end presumably long before the PDF is completely downloaded.

      I do this:

      my $out = pod2pdf(@args); print "Content-Type: application/pdf\n"; print "Content-Disposition: attachment; filename=$username.tasks.pdf\n +\n"; unlink "./pod/$username.tasks.$$.pod"; binmode(STDOUT); return print $out;

      Of course, YMMV depending on the module you use. I think I had hacked POD::Pdf to return the Pdf data instead of just writing it to the file. I don't recall. But, otherwise you could just read the file in and print it:

      my $out; { local $/ = undef; open(PDF, "$file") or die "foo $!"; $out = <PDF>; close PDF; }

      Or whatever fits your fancy.

      Cheers,
      KM

        oooh! Now we're getting to the good stuff:
        print "Content-Type: application/pdf\n";
        print "Content-Disposition: attachment; filename=$username.tasks.pdf\n\n";
        
        I didn't know about that "Content-Disposition" header. That fixes the unlinking problem.

        pause to test

        Neat! This actually solves the entire temporary filename aspect, since I now no longer need a file! ( I can just deliver the content directly). The previous problem was convincing the browser to not try to save pdfprogram.cgi?PARAMETERS=BLAH as the filename.

        Thanks a ton!