Solved

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

Posted on 2004-04-03
9
285 Views
Last Modified: 2012-06-21
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
Comment
Question by:rmgould
  • 4
  • 3
  • 2
9 Comments
 
LVL 5

Expert Comment

by:crazycomputers
ID: 10752483
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
 

Author Comment

by:rmgould
ID: 10752662
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
 
LVL 5

Expert Comment

by:crazycomputers
ID: 10753043
Try turning on warnings ("use warnings;" or append -w to shebang) and run it again.
0
 

Author Comment

by:rmgould
ID: 10753070
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 5

Assisted Solution

by:crazycomputers
crazycomputers earned 125 total points
ID: 10753654
Try changing

$a=pdate("20020101");

to

pdate("20020101");

and see what happens.  (This is the one outside of child_init_hook.)
0
 

Author Comment

by:rmgould
ID: 10753734
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
 
LVL 20

Accepted Solution

by:
jmcg earned 125 total points
ID: 10754786
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
 

Author Comment

by:rmgould
ID: 10771550
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
 
LVL 20

Expert Comment

by:jmcg
ID: 10771686
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

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now