larsen has asked for the wisdom of the Perl Monks concerning the following question:

Developing a web-based programming-contest trainer, I encountered a problem: Perl interpreter, in separate processes, compiles a program, runs it and tests its output, consisting in a file called, for example, exercise_code.out (the program is compiled dinamically because is provided by the user through a web-interface). I need a way to flock program_code.out before its creation, such that no one can test the same exercise.

So I can't use flock primitives, because file does not exist. My solution checked existence of exercise_code.out; could you do something better?

I hope I've been clear :)
Larsen

Replies are listed 'Best First'.
Re: Flocking in advance
by atl (Pilgrim) on Aug 11, 2000 at 15:14 UTC
    Locking something that doesn't exist is indeed not possible. Checking on the existence of a file and then opening/creating it will create you a race condition you should avoid. Two solutions for your problem come to my mind.

    First, if you want to stick to that approach, use a second (empty) file to do the locking on. Your (perl written?) compiler tries to get a lock on that file and doesn't do anything until he gets it (or maybe a timeout occurs).

    Another option is to use unique file names for the output, so multiple submissions can be made at any time. You might use a combination of username and timestamp, for example.

    Andreas

RE: Flocking in advance
by ColtsFoot (Chaplain) on Aug 11, 2000 at 15:23 UTC
    Perhaps you could use "tmpfile" from the POSIX module which
    uses the methof FileHandle::new_tmpfile so that each time a new
    file is generated, that way more than one person can test the
    same exercise.
    HTH
RE: Flocking in advance
by tilly (Archbishop) on Aug 11, 2000 at 15:55 UTC
      Thank you very much. I'll try to explain something more about my application. The application is interfaced to a database containing a lot of exercises and solutions. An exercise consists in a description of the problem (a .ps file), an input file (exercise_code.in) and a output file (exercise_code.out). A solution is called correct iff, provided (exercise_code.in) as input, output produced by the program equals verbatim (exercise_code.out). If a solution is correct, it will be inserted in the database. So a student can see other solutions and learn. Or practice, in order to participate to ACM International Collegiate Programming Contest. As you can see, the entire process is automatizable. So far so good.

      Here's a pseudo code description of my submit script.
      get solution's source code from web form get a valid temp file and store solution in it # Here's my rudimental flocking system while ( -e "exercise_code.in" ) {} get from the database exercise_code.in and exercise_code.out compile solution's source code (using gcc) run the solution (it will produce executable_filename.out) File::Compare executable_filename.out and exercise_code.out if they are the same insert solution in the database else wrong answer!

      I feel I could do something better. Now, I am going to examine your Simple Locking code
      See you
        Be very, very, careful. You don't want someone submitting a rootkit as a sample solution! Were I you I would do some very serious studying of ways of executing untrusted code. Note that there are well-known ways of breaking chroot jails, that is not enough. On many *nix systems you have something called POSIX capabilities (a marketing misnaming since they have essentially nothing to do with real capabilities) that might be able to give you enough protection to sleep at night.

        Other ideas are to use OpenBSD for the test, run the code inside of VMWare (from a stock image that you throw away afterwards) or examine user-mode Linux.

        Personally I like the VMWare and user-mode Linux ideas the best, but YMMV. It is your system after all...