in reply to Fork Me I need help

Thanks for your input. I've done some rewriting:

#!/usr/bin/perl -w #checks for valid email address #usage validemail <file containing email addresses> use warnings; use strict; use Email::Valid::Loose; use Net::DNS; use Parallel::ForkManager; my $pm=new Parallel::ForkManager(20); my $resolver=Net::DNS::Resolver->new(); my $addrfile = $ARGV[0]; my ($is_valid, $host, $ip, @goodaddr, @badaddr, $x, $record, @mx, $add +, @adds); #custom words that make emails invalid to you my @custom = qw( postmaster webmaster ); open (EMAILS, "$addrfile"); while (<EMAILS>){ $_ =~ s/\015//; chomp $_; push @adds, $_; } close (EMAILS); open (BADADDR, ">badmails") || die; open (GOODADDR, ">goodmails") || die; OUTER: foreach $add (@adds){ $pm->start and next; foreach $x (@custom){ if ($add =~ m/$x/){ print BADADDR "$add\n"; #address is bad $pm->finish; } } #if email is invalid move on if (!defined(Email::Valid::Loose->address($add))){ print BADADDR "$add\n"; #address is bad $pm->finish; } #if email is valid get hostname $is_valid = Email::Valid::Loose->address($add); if ($is_valid =~ m/\@(.*)$/) { $host = $1; } $is_valid=""; # perform dsn lookup to check domain @mx=mx($resolver, $host); if (@mx) { print GOODADDR "$add\n"; #address is good }else{ print BADADDR "$add\n"; #address is bad } $pm->finish; } close (GOODADDR); close (BADADDR);

This code works. The only thing I noticed is that the parent will finish before some of the children (is that terminology correct?). If someone was impatient they would think the program is done when actaully it may need another minute to finish. Can this be prevented?

Neil Watson
watson-wilson.ca

Replies are listed 'Best First'.
Re: Fork Me I need help
by Abigail-II (Bishop) on May 30, 2002 at 18:11 UTC
    You only think your code works. But what's going to happen if two children write at once?

    I would use something like:

    use warnings 'all'; use strict; use Email::Valid::Loose; use Net::DNS; use Fcntl qw /:flock :seek/; ... setup stuff ... sub check_addresses; open my $bad => "> badmails" or die "Failed to open badmails: $!\ +n"; open my $good => "> goodmails" or die "Failed to open goodmails: $! +\n"; my $chunk_size = int (@adds / 20) + 1; while (@adds) { my @chunk = splice @chunks, 0, $chunk_size; my $pid = fork; die "Failed to fork: $!\n" unless defined $pid; unless ($pid) { check_addresss @chunk; exit; } } 1 until wait () == -1; # Wait till all children have died. exit; sub check_addr { my $address = shift; ... do some test, return 1 if good, 0 if bad ... } sub check_addresses { foreach my $address (@addresses) { my $handle = check_addr ($address) ? $good : $bad; flock $handle, LOCK_EX or die "Flock failed: $!\n"; seek $handle, SEEK_END, 0 or die "Seek failed: $!\n"; print $handle, "$address\n"; flock $handle, LOCK_UN or die "Flock failed: $!\n"; } }

    Abigail

      I believe you. Clinging to the hope that some of my code is good I tried this using some of your suggestions:

      #!/usr/bin/perl -w #checks for valid email address #usage validemail <file containing email addresses> use warnings; use strict; use Email::Valid::Loose; use Net::DNS; use Parallel::ForkManager; use Fcntl qw/:flock :seek/; my $pm=new Parallel::ForkManager(20); my $resolver=Net::DNS::Resolver->new(); my $addrfile = $ARGV[0]; my ($is_valid, $host, $x, @mx, $add, @adds, $handle); #custom words that make emails invalid to you my @custom = qw( postmaster webmaster ); open (EMAILS, "$addrfile"); while (<EMAILS>){ $_ =~ s/\015//; chomp $_; push @adds, $_; } close (EMAILS); #warning, I will delete existing files open (BADADDR, ">badmails") || die; open (GOODADDR, ">goodmails") || die; foreach $add (@adds){ $pm->start and next; foreach $x (@custom){ if ($add =~ m/$x/){ writebad(); #address is bad $pm->finish; } } #if email is invalid move on if (!defined(Email::Valid::Loose->address($add))){ writebad(); #address is bad $pm->finish; } #if email is valid get domain name $is_valid = Email::Valid::Loose->address($add); if ($is_valid =~ m/\@(.*)$/) { $host = $1; } $is_valid=""; # perform dsn lookup to check domain @mx=mx($resolver, $host); if (@mx) { writegood(); #address is good }else{ writebad(); #address is bad } $pm->finish; } close (GOODADDR); close (BADADDR); 1 until wait () == -1; # Wait till all children have died. exit; sub writegood{ flock GOODADDR, LOCK_EX or die "Flock failed: $!\n"; seek GOODADDR, SEEK_END, 0 or die "Seek failed: $!\n"; print GOODADDR "$add\n"; flock GOODADDR, LOCK_UN or die "unFlock failed: $!\n"; } sub writebad{ flock BADADDR, LOCK_EX or die "Flock failed: $!\n"; seek BADADDR, SEEK_END, 0 or die "Seek failed: $!\n"; print BADADDR "$add\n"; flock BADADDR, LOCK_UN or die "unFlock failed: $!\n"; }

      Alas, now only a couple of blank lines are written to goodmails and badmails. Fork Me!

      Neil Watson
      watson-wilson.ca