Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
Dear wise ones,

I am working on a program that will execute a forked child that will return information back to the parent process. I know that when a fork is executed, the parent and child processes initially have identical copies of the pre-forked environment but that these copies are independent of each other, such that changes made to any part of its environment by either process are not reflected in the other environment.

I decided to see if I could come up with a method whereby a child could in fact modify the value of a variable in the parent. It involves encapsulating the child code into a subroutine to which a reference to a variable in the parent process is passed as an argument. The child modifies the value of the parent variable by accessing that variable via its address, not via its name.

My code is as follows:

use strict;
use warnings;

my $string = "First value";
my $ref_to_string = \$string;

unless (fork)

    {
        do_subroutine ($ref_to_string);
        exit;
    }

print "\nI am the invoking process and my PID is $$\n";

print "invoker $$: The value of \$ref_to_string is $ref_to_string\n";
print "invoker $$: The value of \$\$ref_to_string is $$ref_to_string\n\n";

my $waited_upon_child = wait;

print "invoker $$: The PID of the child upon whom I waited was $waited_upon_child\n\n";

print "invoker $$: The value of \$ref_to_string is $ref_to_string\n";
print "invoker $$: After the call to the subroutine, the value of \$\$ref_to_string is finally $$ref_to_string\n\n";

print "invoker $$: I will now invoke the subroutine directly.\n\n";

do_subroutine ($ref_to_string);

print "invoker $$: The value of \$ref_to_string is $ref_to_string\n";
print "invoker $$: After the call to the subroutine, the value of \$\$ref_to_string is finally $$ref_to_string\n\n";

sub do_subroutine

    {
        print "I am the subroutine and my PID is $$\n";

        my $sub_ref_to_string = shift;

        print "Sub $$: The value of \$sub_ref_to_string is $sub_ref_to_string\n";
        print "Sub $$: The value of \$\$sub_ref_to_string is $$sub_ref_to_string\n\n";
        print "Sub $$: The preceding two messages confirm that I have access to the same\n";
        print "Sub $$: memory location as the calling process even though I may be running\n";
        print "Sub $$: in a different process from that of the calling process.\n\n";

        #   The following sleep instruction simulates time expended if this subroutine
        #   were doing real work

        sleep (4);

        $$sub_ref_to_string = "Second value";

        print "Sub $$: The value of \$sub_ref_to_string is still $sub_ref_to_string\n";
        print "Sub $$: The value of \$\$sub_ref_to_string is now $$sub_ref_to_string\n";

        print "Sub $$: I have changed the value of the scalar referenced by \$\$sub_ref_to_string (Heh-heh)\n\n";
    }



The output from this program is the following:

I am the invoking process and my PID is 95864
invoker 95864: The value of $ref_to_string is SCALAR(0xe96dc0)
invoker 95864: The value of $$ref_to_string is First value

I am the subroutine and my PID is 95876
Sub 95876: The value of $sub_ref_to_string is SCALAR(0xe96dc0)
Sub 95876: The value of $$sub_ref_to_string is First value

Sub 95876: The preceding two messages confirm that I have access to the same
Sub 95876: memory location as the calling process even though I may be running
Sub 95876: in a different process from that of the calling process.

Sub 95876: The value of $sub_ref_to_string is still SCALAR(0xe96dc0)
Sub 95876: The value of $$sub_ref_to_string is now Second value
Sub 95876: I have changed the value of the scalar referenced by $$sub_ref_to_string (Heh-heh)

invoker 95864: The PID of the child upon whom I waited was 95876

invoker 95864: The value of $ref_to_string is SCALAR(0xe96dc0)
invoker 95864: After the call to the subroutine, the value of $$ref_to_string is finally First value

invoker 95864: I will now invoke the subroutine directly.

I am the subroutine and my PID is 95864
Sub 95864: The value of $sub_ref_to_string is SCALAR(0xe96dc0)
Sub 95864: The value of $$sub_ref_to_string is First value

Sub 95864: The preceding two messages confirm that I have access to the same
Sub 95864: memory location as the calling process even though I may be running
Sub 95864: in a different process from that of the calling process.

Sub 95864: The value of $sub_ref_to_string is still SCALAR(0xe96dc0)
Sub 95864: The value of $$sub_ref_to_string is now Second value
Sub 95864: I have changed the value of the scalar referenced by $$sub_ref_to_string (Heh-heh)

invoker 95864: The value of $ref_to_string is SCALAR(0xe96dc0)
invoker 95864: After the call to the subroutine, the value of $$ref_to_string is finally Second value


The dilemma that I have is that it is clear that the child process knows the address of the variable in the parent space that it is to try to change, because upon invocation the child correctly reads and prints the value of the variable at that address. The child then modifies the value of the variable at that address and confirms within itself that the change has correctly taken place, again accessing the value at that address via the reference to that variable.

When the child has finished its work, and the parent has finished waiting on the child, the parent then examines the value of the variable the address of which it had passed to the child. It turns out that the value is unchanged, as if the child had never run. Yet repeatedly across the code for the parent and the child, confirmation is printed that the value of the reference to the variable in question never changes.

My program then goes on to have the parent invoke the child subroutine directly, not by delegating it to a child process, and then it is clear that the subroutine works as intended.

Why would the value at the referenced address be modifiable by the subroutine when running in the same process as the invoker, but not when the subroutine is running in a different process but still clearly has full access to the address of the variable to be changed, as is evident by the fact that at its outset it can read the value at that address placed there by the parent?

Thank you.

In reply to Perl forked processes and variable sharing by fireblood

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (6)
As of 2024-04-19 16:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found