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
|