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

Hi all!

I have written a module similar to CGI::Persistent, but then intended for MySQL.

The idea is simple. Once a scripts initiates a new object, the constructor reads the propper data from the database and thaws it (I use Storable qw(thaw nfreeze) for this) I check wheter an ID was given when calling the ->new routine. If not I read the &CGI::param("id") (or ID) for an ID. The ID is looked up in the DB, the data thawn and given back in the object to the script.

I also have a ->store() routine, which I don't want to force upon my module users so I have it called upon from the ->DESTROY() routine.

This works fine when testing stuff on the shell, but under apache, this doesn't work...

I use base qw(CGI) - so I was wondering wheter my DESTROY isn't called because the CGI::DESTROY is called or if it isn't called because of the way the scripts die under apache's wings...

Thanks in advance 4 all ur answers!

Sinister greetings.
"With tying hashes you can do everything God and Larry have forbidden" -- Johan Vromans - YAPC::Europe 2001
perldoc -q $_

Replies are listed 'Best First'.
Re (tilly) 1: $obj-DESTROY isn't called upon
by tilly (Archbishop) on Jan 31, 2002 at 13:07 UTC
    When you say under Apache, do you mean with mod_perl?

    If so then it is quite possible that the script you are running never actually loses the object (eg it is in a global variable), it survives because it is in a persistent processs, and DESTROY is never going to be called.

    Try using Apache's register_cleanup function to register a function that does your cleanup. To do that you will need to keep track of the created objects, and then do the save in your cleanup function. I haven't done that myself, but recent versions of CGI.pm first check whether $ENV{GATEWAY_INTERFACE} exists, and if it does then does it match /^CGI-Perl\//. If it does then mod_perl is on, they require Apache, then later on:

    if ($MOD_PERL && defined Apache->request) { Apache->request->register_cleanup(\&CGI::_reset_globals); undef $NPH; }
    The $NPH doesn't concern you. The Apache->request bit does. You might do that by having in your constructor something like this:
    if ($MOD_PERL && defined Apache::Request) { Apache->request->register_cleanup(\&saveall); push @OBJ_STORE, $self; }
    and then in saveall save each method in @OBJ_STORE then discard them all. (Check in your DESTROY whether things have been saved.)

    This is untested, but give it a shot and see if it doesn't work.

      Hi tilly! Thnx for the post, but it is not running under mod_perl - I have actualy found the cause of the problem, after an intensive search through the cookbook. I found that when a perl script is instantiated using exec (or similar) DESTROY will never be called upon when the program exits.

      Therefor I now advise in the POD to do a undef $obj; before the script exits. This seems to be the only way to have it run the DESTROY routine... Thanks for your quite usefull post anyway (I can very much use this for another project)...

      Sinister greetings.
      "With tying hashes you can do everything God and Larry have forbidden" -- Johan Vromans - YAPC::Europe 2001
      perldoc -q $_

        Um, all instances of perl under Unix are instantiated using exec(). DESTROY doesn't get called if you script goes away because of a successful exec. How perl was started doesn't matter.

        Now, if the script isn't being run by perl (the separate executable) but is instead being run by a Perl interpretter embedded in some other executable, then your object might not be destroyed until the interpretter is torn down, and that might not happen until much later in such cases. mod_perl is just one example of this. You can usually check $^X to if you have such a case.

        If you avoid putting references to your object into global variables (also known as package variables), then your DESTROY method won't have to wait until the interpretter is destroyed. But inheritting from CGI would probably break that since CGI stores a reference to its first instantiation into a global variable in case you use the "function" interface (vs. of the OO interface).

                - tye (but my friends call me "Tye")