
aw at ice-sa
Nov 21, 2008, 3:08 AM
Post #2 of 5
(371 views)
Permalink
|
Bruce Johnson wrote: > We just moved some cgi scripts over from an ancient system to our new > server running modperl. > > We have require files (that themselves have require files) that check > cookies and login status for these scripts. > > If someone is not logged in, this triggers an exit our of one of the > require files to the login page, the original calling script is sent to > the login as a parameter, along with any parameters IT had. > > Since we migrated to the new system we've been seeing error messages > like this: > > "[Mon Oct 13 00:39:56 2008] [error] ModPerl::Util::exit: (120000) exit > was called at header-apply-locked line 41. Compilation failed in require > at header-apply-combined line 17. Compilation failed in require at > /home/oraweb/perl/apply/applymyapplication.pl line 9." > > This happens when the exit is triggered in the nested require file. > which is code like this: > > # Check to see if the person was logged in, and if not go to login page and > # pass the url and parameters > if (!defined($UUAff) || !defined($UUPID)) { > $url = "$path/login.pl?prev_url=$prev_url$llist"; > print "Location: $url\n\n"; > exit; > } > 1; > > > What is this error, is it a problem, and what do I do to avoid it. > Hi. Until someone else more qualified provides a better and more precise explanation, let me try : In short : I think you have a real problem, in the sense that those scripts do not seem to be compatible with running them under mod_perl. In my opinion, you will either have to make some serious modifications to them to run them under mod_perl, or you will have to disable mod_perl for those scripts. In many more words : When you run a normal perl script (outside of Apache), the perl interpreter is loaded fresh, reads your script, compiles it to some bytecode, then runs the bytecode. When it encounters an "exit" instruction, it not only stops executing the script, but it also stops the perl interpreter itself and returns to the command-line. That is also what happens when you run perl cgi-bin scripts, without having mod_perl installed. mod_perl, among other things, consists of "embedding" a persistent perl interpreter into Apache itself. Because it is supposed to stay alive there, and be used for many script executions in a row, it arranges not to terminate itself when it encounters an "exit". That's why it redefines "exit", to catch it and not really exit, but just stop the script, clean up, and be ready to execute the next script. mod_perl can dramatically improve the speed of running perl cgi-bin scripts, for two main reasons : 1) the perl interpreter is "embedded" in Apache, so it does not have to be reloaded each time you run a perl cgi-bin script 2) when the embeded perl interpreter runs a perl cgi-bin script once, it compiles it, then executes the "compiled" code, but it keeps the compiled version available. So the next time it has to run the same script, it does not have to start from scratch, it can just run the already-compiled version. In order to do that however, mod_perl initially "re-works" the original script quite a bit. Basically it converts it from a stand-alone script, by wrapping it into some code which calls the original script as a subroutine. One of the things it does for that, is to replace the original "exit" calls of the script, so that they will not really exit the perl interpreter, but just do a "return" from the now "subroutined script". However, all of this is not really compatible with the usage of "required" pieces of code which themselves call "exit" (which seems to me a rather strange way of programming anyway). The way I see this running is : - perl reads and compiles the top cgi-bin script - during this compilation, it encounters a "require othercode.pl". - it suspends the compilation of the original script, pulls in "othercode.pl", compiles it and runs it. It expects this piece of code to do things like initialising new symbols etc.., and end with "return 1". - at which point it continues compiling the original script, with maybe now some changed environment. - then it runs the original script, now transformed into a subroutine, expecting it to end in an "exit" (which has been in the meantime transformed into a "return"). However now, in your scenario, it encounters an "exit" in the code it pulled in for the "require othercode.pl". What should it do with this ? It is still in the process of compiling the original script.. It can certainly not do a real "exit", because that would terminate the supposedly persistent perl interpreter in Apache. It can also not do a "return", because to what would it return ? So, this is stuff that might well work in the context of a non-persistent perl interpreter (as you would have it in an Apache without mod_perl), but in a mod_perl context this is really bizarre. And that is probably why you see all these error messages. In my subjective opinion thus, I believe you have the following options : - forget about running this, as such, under mod_perl, and run them under a non-mod_perl environment, as normal cgi-bin scripts. - or, hire some good mod_perl programmer to have a look at these scripts and see if they can be modified to run under mod_perl (Torsten, are you there ?) - or, considering that they seem to be used for some AAA purpose, have a look at the numerous AAA-like modules on CPAN in the Apache2::auth* series, and see if you could not simply replace these scripts by something that fills the same purpose (even if for that you have to slightly modify one of the existing Apache2::auth* modules) In my opinion still, the 3rd option, if feasible, would be the best, because it would also give you a much bigger boost in performance, and probably a much easier and clean configuration, compared to the kind of "script calling script" method that the current scripts are apparently using. There might be another option still : looking at your description above (very good by the way), I have a feeling that it might be possible to replace the "require-s" by subroutine calls, which would not have this issue of "exit within a require-d file". I have not seen the code of the required files of course, and I do not know how many scripts you would have to modify, so this is a rather risky shot. But having some experience with mod_perl based AAA modules, I have some idea of how they usually work and what they do, and unless yours are particularly devious, that should not be so outlandish. A project for a student maybe ?
|