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

Hi,

I've been using a Perl portal (Web-App) for a while now and we've recently discovered a problem on certain servers. It looks like the problem is confined to servers that have Perl 5.8.1 installed. The problem seems to be concerned with either file locking, or more likely with require statements.

As an example, the index.cgi has a require statement that calls config.pl and a number of other files. This structure has worked well for us and is still working prefectly on many sites that have not upgraded to Perl 5.8.1, however, newer sites are returning the following error:

Software error:
Can't modify constant item in lock at index.cgi line 256, near "FILE)"
Execution of index.cgi aborted due to compilation errors.

I can provide code if necessary, but initially I'm looking for a general answer on whether this functionality has changed. I've looked on Perl.org but there seems to be no mention of this. It's very possible that the existing code was running in a sloppy fashion that has now become broken because Perl has tightened up it's definitions.

Any help much appreciated!
Alatar

As requested: here's the relevant code:

elsif ($action eq "forum") { $forum = qq~$cgi?action=forum&board=$currentboard~; if ($currentboard ne "" and $op eq "") { open(FILE, "$boardsdir/$currentboard.dat") || error("$err{'001 +'} $boardsdir/$currentboard.dat"); lock(FILE); chomp(@boardinfo=<FILE>); unlock(FILE); close(FILE); $boardname = "$boardinfo[0]"; $boardmoderator = "$boardinfo[2]"; open(MODERATOR, "$memberdir/$boardmoderator.dat"); lock(MODERATOR); chomp(@modprop = <MODERATOR>); unlock(MODERATOR); close(MODERATOR); $moderatorname = "$modprop[1]"; require "$sourcedir/forum.pl"; messageindex();
The error refers to the line "lock(FILE);" and the reason I think require might be the problem is because I think the global variables are not being carried through from the code called in the require statement.

Also, by previous version of Perl, I mean all different flavours. The only one that seems to have a problem is Perl 5.8.1

Replies are listed 'Best First'.
Re: Has the "require" functionality changed in Perl 5.8.1?
by simonm (Vicar) on Nov 28, 2003 at 20:44 UTC
    I'm not sure what the specific problem is in this case, but I would bet that this code isn't doing what you intended.

    The lock() function is for use in threaded applications. It does not lock files.

    The discussion that was linked to describes a bunch of CGI scripts, which typically aren't multi-threaded, so I would assume that what's intended is a file lock, to prevent inter-process conflicts, rather than a variable lock, to prevent inter-thread conflicts within a single process.

    See the flock function instead.

    Update: I've downloaded and looked around the code from the webapp site linked to above, and found that it does define a lock() function that in turns calls the built-in flock().

    Perhaps the problem is that for some reason the cgi-lib/forum.pl file is being loaded before cgi-lib/subs.pl?

    As a longer-term solution, you might find that renaming the lock function in subs.pl to lock_file, and similarly changing all of the calls to match, might be sufficient to fix it.

      Thanks, this looks like a possible solution. I'll test it out and let you know if it works!

      Thanks again,
      Alatar

        Well Done SimonM, you were right on the money. We're working on a patch now. Thanks for all the help!

        Alatar

Re: Has the "require" functionality changed in Perl 5.8.1?
by Joost (Canon) on Nov 28, 2003 at 15:54 UTC
    Since you did not specify the "other" perl versions or code and I cannot smell from here what the code looks like, I can only point you to the perldelta and associated manpages (perl56delta, perl58delta etc)

    Maybe it would help to put index.cgi lines 250 - 260 somewhere in the thread...

    Joost.
    -- #!/usr/bin/perl -w use strict;$;= ";Jtunsitr pa;ngo;t1h\$e;r. )p.e(r;ls ;h;a;c.k^e;rs ";$_=$;;do{$..=chop}while(chop);$_=$;;eval$.;
Re: Has the "require" functionality changed in Perl 5.8.1?
by ysth (Canon) on Nov 28, 2003 at 17:43 UTC
    Exactly which versions does it work on? Are you checking to see if your require succeeds? Is lock() defined in the require'd file? Can you put in a warn "whoops: lock not defined" if !defined &lock;

    There was a change that broke some uses of require() just after 5.8.1, but that was retracted. It's possible you have an aggressive vendor that is including extra changes in their perl release.

Re: Has the "require" functionality changed in Perl 5.8.1?
by Abigail-II (Bishop) on Nov 28, 2003 at 15:53 UTC
    Changed since when? AFAIK, the require statement hasn't changed between 5.8.0 and 5.8.1, but if you want to be sure, read the perldelta manual page. Furthermore, the error message you give doesn't indicate a problem with 'require' at all.

    Abigail

      The thread on the Perl Portal (web app) site seems to be where Alatar is coming from. Through that it works fine in versions before 5.8.1 . I have to get a train but the only comment I can say after downloading and reading the code, is very little comments, all vars are global and no strict, it hurts the head to swim through. I will pick this up at home though because it is not IE and anything that has me not tracing problem in IE is a good train of thought.

      Update I would have to believe that simonm is right. The lock subroutine should be renamed and using a search and replace utility rename all calls to the sub also.

      "No matter where you go, there you are." BB
Re: Has the "require" functionality changed in Perl 5.8.1?
by edoc (Chaplain) on Nov 28, 2003 at 16:48 UTC

    maybe I've had too much to drink, but...

    what's 'lock'? is that a function you have defined? from what I can find it has to do with threading.. unless I'm missing something, that's meant to be 'flock'..

    cheers,

    J

      From http://www.perldoc.com/perl5.8.0/pod/func/lock.html

      quote

      lock

      lock THING

      This function places an advisory lock on a shared variable, or referenced object contained in THING until the lock goes out of scope.

      lock() is a "weak keyword" : this means that if you've defined a function by this name (before any calls to it), that function will be called instead. (However, if you've said use threads, lock() is always a keyword.) See threads.

      unquote

      Which would mean that you could lock a FILEHANDLE but it is not the same functionality as flock. Update Or because it is a weak function as simonm pointed out below if the require calls are after its use instead of before it will use the internal lock functin instead of the user defined lock function.

      "No matter where you go, there you are." BB