Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re: mixing multisockets and forks

by tachyon (Chancellor)
on Mar 29, 2004 at 00:12 UTC ( [id://340457]=note: print w/replies, xml ) Need Help??


in reply to mixing multisockets and forks

Have you heard of the concept of simplifying to a small test case? Anyway that said AFAIKS the problem is that in your incredibly misnamed new_thread routine you are doing this:

if ( $pid = fork() ) { $threads++; # you mean kids return $pid } # this is kid code # kid does socket but.....then...... exit($result);

So the child process is exiting but you are not decrementing the '$thread' count, at least in the code presented. Nor are you communicating its death to the parent. So the reason you are getting a no children error is simple -> *there are no children* because they have finished but the parent simply does not know it.

At a glance I don't see how you think the IPC between parent and child is going to work, and given the length of your sample and what I find really inaccurate and annoying names (ie a forked kid is not a thread) a glance is all it is going to get. When you fork parent and child get copies of all data and handles. Independent* copies so if the kid does stuff to the data the parents data remains unchanged.

* yes I understand COW.

cheers

tachyon

Replies are listed 'Best First'.
Re: Re: mixing multisockets and forks
by fxmakers (Friar) on Mar 29, 2004 at 00:50 UTC
    Thanks for your reply!
    I'm a little confused...
    1st of all, yes, my "threads" could be renamed to children processes, sorry :)

    The $SIG{CHLD} is called when a child process has finished, so we can retrieve its exit($result) using waitpid() and put the $result into the $status{$pid} hash.
    use POSIX ":sys_wait_h"; $SIG{'CHLD'} = \&REAPER; # manage moribound children sub REAPER { my $pid = 0; while (($pid = waitpid(-1, &WNOHANG)) > 0) { $status{$pid} = $?; } $SIG{'CHLD'} = \&REAPER; }


    The $threads decrement is done in the &timer_online, comparing the $status $pid with the client's pid list.


    If you launch the 2nd portion of code (the fake "scan"), everything is running fine, the parent gets the finished child's $result using the &REAPER routine.

    Here's a simple code:

    use strict; use POSIX ":sys_wait_h"; $SIG{'CHLD'} = \&REAPER; sub REAPER { my $pid = 0; while (($pid = waitpid(-1, &WNOHANG)) > 0) { print STDOUT "$pid returned $?\n"; } $SIG{'CHLD'} = \&REAPER; } sub new_thread { my $result = 0; if (my $pid = fork()) { return($pid); } $result = 1; exit($result); } my $child = &new_thread(); print STDOUT "got a new child: $child\n"; for (;;) {} 1;


    This way we can retrieve the $result.

    If this works fine without the select() and vec() socket management, why are the fork()'s processes problematic when using them?


    The simple complete code mixing them:
    use strict; use POSIX ":sys_wait_h"; use IO::Socket::INET; $SIG{'CHLD'} = \&REAPER; sub REAPER { my $pid = 0; while (($pid = waitpid(-1, &WNOHANG)) > 0) { print STDOUT "$pid returned $?\n"; } $SIG{'CHLD'} = \&REAPER; } sub new_thread { my $result = 0; if (my $pid = fork()) { return($pid); } sleep(3); $result = 1; exit($result); } my %socklist = (); # hash table of sockets my $bit = ''; # connect to the IRC server my $socket = &open_socket("tcp", "irc.creatixnet.com", 6667, 3); sub open_socket { my ($proto, $host, $port, $timeout) = (shift, shift, shift, shift); my $socket = IO::Socket::INET->new( Proto => $proto, PeerAddr => $host, PeerPort => $port, Timeout => $timeout ); if (!$socket) { return(0); } return($socket); } if (!$socket) { die("can't connect"); } &add_socket($socket, "IRC"); sub add_socket { my ($socket, $type) = (shift, shift); $socket->autoflush(1); $socklist{$socket}{'sock'} = $socket; $socklist{$socket}{'type'} = $type; $socklist{$socket}{'fileno'} = $socket->fileno(); vec($bit, $socklist{$socket}{'fileno'}, 1) = 1; return(0); } print $socket "USER zxf sdf sdf sdf\n"; print $socket "NICK sdfsdfg\n"; print $socket "JOIN #fx\n"; my $child = &new_thread(); print STDOUT "got a new child: $child\n"; sub loop_socket { my $rin = $bit; $rin =~ /[^\0]/ || next; my $idx = select($rin, undef, undef, 1); my $buffer = ""; $idx || next; $idx > 0 || die($!); my %list = %socklist; while ($idx && (my ($socket, $value) = each(%list))) { $socket = $value->{'sock'}; if (vec($rin, $value->{'fileno'}, 1)) { $buffer = <$socket>; print + STDOUT "IRC: $buffer"; } } return(0); } for (;;) { &loop_socket(); } 1;

    When children exits: No children at test.txt line 82

    :(
    Cheers

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://340457]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (3)
As of 2024-04-19 00:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found