in reply to Re^3: Defining global variable in a subroutine
in thread Defining global variable in a subroutine

Eliya,

If you take a look at Re: Accessing hash from within module, which I commented on how to use/update globals in the parent, I think it gives enough information to explain what I'm talking about.

Also remember, it you use 'our' in the child, it creates the global in the parent space, and not in the child's address space. That's why you need to LOCK/UNLOCK the global that you are using.

Good Luck!

"Well done is better than well said." - Benjamin Franklin

  • Comment on Re^4: Defining global variable in a subroutine

Replies are listed 'Best First'.
Re^5: Defining global variable in a subroutine
by dave_the_m (Monsignor) on Feb 22, 2012 at 16:21 UTC
    An 'our' variable (or any normal variable for that matter) is not shared between parent and child after a fork.
    our $x = 1; my $f = fork; die $! unless defined $f; if ($f) { # parent sleep 1; print "parent: x=$x\n"; # prints 1 } else { $x = 2; exit; }

    Dave.

Re^5: Defining global variable in a subroutine
by Eliya (Vicar) on Feb 22, 2012 at 16:24 UTC

    After having read the linked thread, I'm still not sure what your message is with respect to forking.

    For all practical matters, there's no real differnce between accessing an "our" vs. a "my" variable from within a child process.  In both cases, the child has access to the variable's value as it was at the time of the fork, but as soon as either the child or the parent modifies it, they become different entities stored at different memory locations (due to the copy-on-write mechanism).  In other words, neither the child nor the parent can "update" the variable in the other process.

    #!/usr/bin/perl -wl use strict; our $var = "foo"; # my $var = "foo"; # same thing wrt fork sub modify_var { $var = shift; } unless (fork) { sleep 1; print "child: $var"; modify_var("bar"); print "child: $var"; } else { modify_var("baz"); wait; print "parent: $var"; }

    prints (as expected):

    child: foo child: bar parent: baz

    As I'm reading your comment, you'd expect the output to be (?)

    child: baz child: bar parent: bar

    As you can see, the variable is not shared.

      Eliya,

      I downloaded and tested your script, and it does exactly as you say.

      So I have a production 20,000 line application that does the following:

      Parent process

      • Startup and initialize all "common" hashes (ie %SYS, %Account, ... )
      • Establish socket communication
      • fork children that wait on socket (usually at least 4 children, but in one case their are 128 children)
      • Maintain children

      Child process

      • wait on socket
      • do work when communication received (GET/POST data) from cgi script called from web server and returns html to the cgi script, which returns the html to the server.
      • exit after nn number of calls

      So that's the high level picture. Now the actual work that goes on is all done by subroutine calls from a child as follows:

      • User logs in with account/password.
        • Child verifies account and creates a $Account{user}{ } HoH .
          Note: each user has about 60-100 hash fields. child returns html to caller.
      • user clicks on things they want
        • each click results in call to different children that use the $Account{user}{ HoH } to read/update/delete values. Notice we don't know which child will be working on which user. We use *nix logging so we can see the different children($$) being called by different users.
      • user logs out and child undefines all hashes created for user.

    So based upon you script this shouldn't work, but it does.

    The parent doesn't look at any of the 'our' hashes, only the children and each child logs information that they have used from the global hashes.

    Now I'm confused at a different level.

    Thank you

    "Well done is better than well said." - Benjamin Franklin

        Where does the parent use any value set in a child?
        Parent process ... Startup and initialize all "common" hashes (ie %SYS, %Account, ... )

        How does it initialises these hashes? I guess they are tied hashes, perhaps something created with IPC::Shareable.