Basically i have a port scanner. It uses Socket to connect. I need to loop through a list of IP's and for each IP loop through a list of ports. Each port is checked to see if a tcp connection can be made. To add a time out facility for unreachable or fire walled servers I fork each IP check to a new process. this new process includes
$SIG{ "ALRM"} = sub { print "TIME_OUT! at $timeout\n"; exit; }; alarm ($timeout);
I need to be able to make the main program wait until the child process has either died a natural death or has been killed by it's alarm/exit call. Using  wait(); sort of works ... that is the main program seems to run through the loops forking a new process for each IP check (this could be thousands of processes) and then each child seems to get on with it's stuff one at a time. I don't understand why the loops don't just wait for the child to die before starting a new one. I suspect I am using wait() all wrong. A simple way would be to put the IP check part of the script in a separate file and call it with system("./check.pl $ip $port");. But I cant believe it's not possible to do this in one script! A simplified copy of the code so far:-
require 5.002; require DBI; use strict; use Socket; use POSIX "sys_wait_h"; my ($pid, @port_range, @ip_list, $remote, $port, $timeout, $wait); #----------- config -----------# $timeout = 10; @port_range = qw (8080 6969 80 8081 8080 8000 3128 555 657 889 1180 1181 1182 1183 1184 1185 11012 25318 25719 6969 886); @ip_list = qw (196.2.49.19 grunt.mweb.co.za mweb.co.za); #this will be + populated dynamically from a DB #----------- config -----------# foreach $remote (@ip_list) { foreach (@port_range) { if ($pid = fork) { $wait = wait (); print "Running with port $_ and \$pid $pid \$wait $wait \$? +$? \n"; $port = $_; test ($remote, $port, $pid, $timeout); kill 9, $pid or die "KILL FAILED"; #not necessary? exit; } } } ########################################################### ## SUB ROUTINES ## ########################################################### sub test { my $remote = shift; my $port = shift; my $pid = shift; my $timeout = shift; my ($iaddr, $paddr, $proto); $SIG{"ALRM"} = sub { print "TIME_OUT! at $timeout\n"; exit; }; alarm ($timeout); $iaddr = inet_aton ($remote) or die "no host: $remote"; $paddr = sockaddr_in ($port, $iaddr); $proto = getprotobyname ('tcp'); socket (SOCK, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; if (connect (SOCK, $paddr)) { print "WE HAVE A CONNECTION!\n" } else { die "connect: $!"; } close (SOCK) or die "close: $!"; } exit;

edited: Fri Apr 25 05:01:24 2003 by jeffa - added readmore tag


In reply to New Child to Wait for First Child to Die by spike_hodge

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



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.