WeBWorK Problems

questions about how pg macros get loaded

questions about how pg macros get loaded

by Jason Aubrey -
Number of replies: 2
Hi All,

This question is about how pg macro files get loaded in loadMacros(). I was going to email this question to Mike and Gavin, but I thought some others might have something to add many others might be interested in understanding better how this works. I want to clean up the apache error log noise generated by webwork to remove spurious warning messages.

One source of a lot of noise in the error log seems to be from macrofiles being re-loaded over and over, generating entries like:

Subroutine student redefined at (eval 2539) line 27, <MACROFILE> chunk 1.
Subroutine computer redefined at (eval 2539) line 37, <MACROFILE> chunk 1.
Subroutine moreWork redefined at (eval 2539) line 50, <MACROFILE> chunk 1.

As I understand it, this can be prevented by including a subroutine of the form

sub _macrofilename_init {
initialization code

As one step to clean up the error log, I am intending to add the necessary init subroutines to macro files that are missing them. But, I'd like to understand the behavior a little more before I do.

I can't see any reason why adding empty init subroutines to marco files that are missing them would cause any problems, but I've found a lot of macro files that do not include this init subroutine, and it looks to me like only some macro files that do not include this subroutine generate such warning messages. (Maybe they're not being used?)

So, for example, parserOrientation.pl (from the Orientation problem set in courses/modelCourse) generates a lot of such noise, whereas, for example, Gavin's


does not seem to generate any such noise.

Here's another strange (to me) example from the error log. The function Comb is defined in pg/macros/PGcommonFunctions.pl. There are two courses on the server which contain the same definition of Comb in a macro file in their templates/macro directories (in one it's called PGcommonFunctions.pl, and in the other PGAuxilliaryFunctions.pl). In both cases the templates/macro/ file has the appropriate init subroutine. But in the error log a bunch of

Subroutine Comb redefined at (eval 1762) line 137, <MACROFILE> chunk 1.

Based on how I *think* the PGloadfiles::loadMacros subroutine works, this error comes from the redefinition of Comb in the <course>/templates/macro/PGauxilliaryFunctions.pl since loadMacros won't reload PGcommonFunctions.pl due to the fact that main::_PGcommonFunctions_init is already defined.

So then my question is that when PGauxililaryFunctions "redefines" Comb, what is the scope of the redefnition? I don't understand how mod_perl uses perl processes, but for example, does Comb get redefined "globally" (e.g. in the whole perl interpreter process in which the PGauxilliaryFunctions.pl file is loaded)? Is it somehow limited to the course or does that redefinition get shared between requests in separate courses that are handled by the same perl interpreter process?

In reply to Jason Aubrey

Re: questions about how pg macros get loaded

by Michael Gage -

Is it somehow limited to the course or does that redefinition get shared between requests in separate courses that are handled by the same perl interpreter process?

My understanding is that the redefinition will hold for problems served later to different courses by the same child process.  This could generate a bug which would be very difficult to find if some course redefined a commonly used macro.  Other courses could suddenly find that their problems behaved rather strangely and there would be no obvious reason for it.

To my knowledge this hasn't happened yet because fortunately no one has tried to redefine macros (they add new ones, but don't redefine old ones).  

This is an experiment worth trying just to make sure that this is a real potential problem and not a theoretical one. If it's real then resolving it will take some fundamental redesign of the loadMacros subroutine.

In reply to Michael Gage

Re: questions about how pg macros get loaded

by Davide Cervone -
I don't think that redefining macros in the main:: namespace gets transfered to the next invocation of the same child process (because main:: is set up new in the safe compartment for each invocation). If it did, then you would get a lot more of these messages, since any subroutine defined in one problem would then carry over to the following problems processed in the same child, and if it processed the same problem twice, the second time would "redefine" that subroutine since it would be left over from the first time around.

But I do think that redefining items in the preloaded namespaces (like Parser:: or Value::) would hold over. These are added to the safe compartment as pointers to the ones outside the safe compartment, so changes to them affect the next safe compartment. I know that it did at one point, but haven't checked recently, and I think I remember Sam working on changing how the safe compartment handled these external references.