[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 295
  • Last Modified:

Problem Calling Embedded Function within OO Perl - Namespace Issue??

I am obviously missing something in this simplified example.  I have a 'custom module' for the function I have written over time.
This module uses function from other modules.  For this example - I am using a function from the Date::Manip module.

I am trying to use these functions from an instance of the Net::Server class.  When I call my custom function from a normal perl program or from another module - I have no problem.  When I call my custom from within the child_init_hook sub of the Net::Server module - the ParseDateString function causes the subroutine to end.  Note that no error message occurs and Net::Server continues to run - the sub routine (child_init_hook) just stops executing.

What makes this problem even more bizzare is that if I call my test function 'pdate' before I start the run method (note: i have this line commented out in the text below)- everything works fine.  I am obviously missing something obvious about object oriented perl.


************ Sample Code - Main Program

#!/export/opt/perl/5.8.0/bin/perl

package MyPackage;
 
  use mod
  use vars qw(@ISA);
  use Net::Server::PreFork  qw(:DEFAULT /^/);
  @ISA = qw(Net::Server::PreFork);

#$a=pdate("20020101"); # If this line is not commented out - pdate in child_init_hook works!!

  MyPackage->run();
  exit;

  sub child_init_hook
  {

    print "initializing process id $$\n";
    $a=pdate("20020101");

    print "f $a\n";

  }

1;

********** Sample Module

#!/export/opt/perl/5.8.0/bin/perl

package mod;

require Exporter;
use base qw(Exporter);
use vars qw(@EXPORT @EXPORT_OK @INC);
@EXPORT = qw(&pdate);
use Date::Manip;
sub pdate
{
  my ($y) = @_;
 
  print "bef\n";
  $a=ParseDateString($y);
  print "after $a\n";
}
1;


0
rmgould
Asked:
rmgould
  • 4
  • 3
  • 2
2 Solutions
 
crazycomputersCommented:
Try declaring $a first:

  sub child_init_hook
  {

    print "initializing process id $$\n";
    my $a=pdate("20020101");

    print "f $a\n";

  }

Also, if you are writing a module *** put "use strict;" at the top! ***  There are very good reasons to force variable declaration, and it just might solve this problem.
0
 
rmgouldAuthor Commented:
I do use strict in my actual code.  I did not include it when making this simple example.  Just to check - I did declare my variables first.  There was no effect.  To show the output I included it below.  You can see that the function 'pdate' does not go further than the ParseDateString call.  

*************

2004/04/04-13:41:45 MyPackage (type Net::Server::PreFork) starting! pid(16543)
Port Not Defined.  Defaulting to '20203'
Binding to TCP port 20203 on host *
Group Not Defined.  Defaulting to EGID '201 601 201'
User Not Defined.  Defaulting to EUID '60128'
initializing process id 16544
bef
initializing process id 16545
bef
initializing process id 16546
bef
initializing process id 16548
bef
initializing process id 16547
bef

*****************

If I take out the comment from
  #$a=pdate("20020101"); # If this line is not commented out - pdate in child_init_hook works!!

in the original post I get this output which is correct... i just don't get it...

**********

2004/04/04-13:46:45 MyPackage (type Net::Server::PreFork) starting! pid(16798)
Port Not Defined.  Defaulting to '20203'
Binding to TCP port 20203 on host *
Group Not Defined.  Defaulting to EGID '201 601 201'
User Not Defined.  Defaulting to EUID '60128'
initializing process id 16802
bef
initializing process id 16803
bef
after 2002010100:00:00
f 1
after 2002010100:00:00
f 1
initializing process id 16804
bef
initializing process id 16805
bef
after 2002010100:00:00
f 1
after 2002010100:00:00
f 1
initializing process id 16806
bef
after 2002010100:00:00
f 1




0
 
crazycomputersCommented:
Try turning on warnings ("use warnings;" or append -w to shebang) and run it again.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
rmgouldAuthor Commented:
My current version has 'use warnings' added in addition to properly declaring all variables.  The output above is from that code.  No warnings are currently given.
0
 
crazycomputersCommented:
Try changing

$a=pdate("20020101");

to

pdate("20020101");

and see what happens.  (This is the one outside of child_init_hook.)
0
 
rmgouldAuthor Commented:
does not change anything.  Remember if the pdate call outside of the child_init_hook is called (ie that line is not commented out in the original post) - the whole thing works fine to begin with.  I think the problem has to lie in the namespace of the module.  If I had to guess - somehow the custom module had its namespace overridden by the namespace of the net server class.  

Perhaps you can try saving my 2 examples into 2 files test.pl and mod.pm and see if you replicate the output I am seeing.
0
 
jmcgOwnerCommented:
I don't have a complete answer for you, but maybe what I say can be helpful....

The symptoms you describe look like a sort of dynamic loading problem, but I cannot see just now where it arises. The Date::Manip module itself does not use dynamic loading, but one of the modules it uses may.

The documentation for the Net::Server::PreForkSimple module mentions this:
=======================
$self->child_init_hook()

This hook takes place immeditately after the child process forks from the parent and before the child begins accepting connections. It is intended for any addiotional chrooting or other security measures. It is suggested that all perl modules be used by this point, so that the most shared memory possible is used.
=======================

By calling pdate( ) once before run( ), you are following this advice. This ensures that the Date::Manip::Date_Init function is called in the context of the parent process, before any forks, and Date_Init is called only once -- in the children, the Date_Init call is avoided because it is flagged as already having run.

But in looking through the source of Date_Init, I still don't see any outstanding culprits for why it would work any differently when run in your child processes. They should all start with the Date::Manip module in the same state it was in before the fork. It does not appear to use any file locking while attempting to access its configuration file. Unless your OS is holding things up because of the near-simultaneous attempts to read the config file, I'm baffled as to why you see the symptoms that you do.

The good news is that you avoid the problem by following the module designer's advice.
0
 
rmgouldAuthor Commented:
I found the answer on from a google newsgroup search.  The answer seems to be a problem (feature) with the 'Prefork' component of Net::Server.  If I use 'Fork' vs. 'PreFork' all is well.  The other post had no explanation - but as I don't really need to prefork given my anticipated volume - I am happy with only a forking server.  tkx to all.  splitting the points for the effort given...
0
 
jmcgOwnerCommented:
You must have excellent Google skills -- I could not find anything helpful on the web.

Using the Fork instead of Prefork version means that you are much less likely to get into the startup situation of having all of several children simultaneously tring to run Date_Init. You'd still be well advised to call pdate in the parent before any forks, since having to run Date_Init anew on every transaction is a waste and may slow your response time just a wee bit.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 4
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now