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

Hi monks,

in a very small prefork proxy server script, see below, I want to found which forked child (PID) process the current URI request.
In my tests I get only PID 0 (Ex: child 0 accept request URI: http://web.com/)

Best regards
Josef
#!/usr/bin/perl -w # Description: preforker proxy use 5.16.0; use HTTP::Daemon; use LWP::UserAgent; use Fcntl ':flock'; # global variables my $ip = '127.0.0.1'; my $port = '3128'; my $MIN_CHILDREN = 5; # number of children to maintain my $MAX_REQ_PER_CHILD = 30; # number of req processed per child my %children = (); # keys are current child process IDs my $children = 0; # current number of children $| = 1; my $agent = LWP::UserAgent->new; $agent->agent("perl proxy"); # establish SERVER socket, bind and listen. my $master = HTTP::Daemon->new( LocalPort => $port, LocalAddr => $ip ) or die "Cannot create master socket: $!\n"; # create initial children for (1..$MIN_CHILDREN) { &newChild($master) } # keep children - a never ending loop for the parent process which # just monitors dying children and generates new ones while (1) { sleep; for (my $i = $children; $i < $MIN_CHILDREN; $i++ ) { &newChild($master) } } exit (0); ################################################################### ### Subs ################################################################### # newChild - a forked child process that actually does some work sub newChild { my $socket = shift; my $pid; defined ($pid = fork) or die "Cannot fork child: $@\n"; if ($pid) { # parent code $children{$pid} = 1; # child is using this pid $children++; # Increase the child counter print "forked new child with PID $pid, we have now $children c +hildren(s)\n"; } &child_execute($socket) unless $pid; } sub child_execute { my $master = shift; my $i = 0; while ($i < $MAX_REQ_PER_CHILD) { # Loop for $childLifetime reques +ts $i++; flock($master, 2); # LOCK_EX my $slave = $master->accept or die "accept: $!"; flock($master, 8); # LOCK_UN $slave->autoflush(1); my $request = $slave->get_request; my $url = $request->url; # which PID execute this request??? print "child accept request URI: $url\n"; my $response = $agent->simple_request($request); if ($response->is_success) { my $content = $response->content} $slave->send_response($response); close $slave; } exit (0); }

Replies are listed 'Best First'.
Re: How to find the PID for executed URL request?
by locked_user sundialsvc4 (Abbot) on Dec 10, 2013 at 15:46 UTC

    I detect a few mixed-concerns here ... that $children array/hash is not going to be handled correctly because entries will never get removed from it, and why do you need it anyway?   (You don’t.)

    Start by taking advantage of what has already been done:   Parallel::ForkManager.

    The parent process should spawn children, and otherwise keep the thread-pool full.   It doesn’t need to know their PIDs, because the children should be completely autonomous.

    The children do know their own PID, and they shouldn’t need to know of any other.   As they complete units of work, they can stamp the result-record with their own PID, as well as starting/ending times or whatever else you need to know.   Each worker-bee has no need to know how many other bees are in the hive.   Each worker should also have exception-handling logic ... e.g. eval {...} ... so that a runtime error will not kill the process.   Ideally, the process should live as long as it wishes to ... perhaps forever.

    One more thought:   can you reduce this script just to the child-process logic, and use a shell-script (or the Unix “background job” capability) to run them?   The process would simply run (in an error-resistant way) until it had no more work to do, and you could choose to run as many of them in-parallel as you like.   In one past-life, I saw an extremely-useful variation of the Unix xargs command which allowed you to spawn n parallel copies of the specified command (basically what ForkManager does), and they used it all over the place in their jobs and scripts.   Just a thought, but a good one.   I thought it was extremely simple and elegant.

      Hi sundialsvc4,

      the daemonize routine was not posted now, the $children will be handled here. The suggestion with Parallel::Forkmanager is excellent, on the next step I will use it.
      Right, the children do know their own PID and perhaps their accept() with the URL. My question remain.
      Josef
Re: How to find the PID for executed URL request?
by oiskuu (Hermit) on Dec 10, 2013 at 20:20 UTC
    Judging by the "which PID" comment line, you want the child PID, in the child itself. If so, use $$.
    print "child $$ accept request URI: $url\n";
      Excelent oiskuu, you get my the right hint.
      Best regards
      Josef