This queue is for tickets about the Net-Ping CPAN distribution.

Report information
The Basics
Id:
31697
Status:
open
Priority:
Low/Low
Queue:

People
Owner:
Nobody in particular
Requestors:
kinpoo [...] gmail.com
Cc:
AdminCc:

BugTracker
Severity:
(no value)
Broken in:
(no value)
Fixed in:
(no value)



Subject: When using multi-threads, it will return with fault.
Date: Wed, 19 Dec 2007 19:45:48 +0800
To: bug-Net-Ping@rt.cpan.org
From: Kinpoo <kinpoo@gmail.com>
When using multi-threads, it will return with fault.

#./ ping.pl 255
...
-- 66.94.234.14 -- -- -- -- -- --
-- ping $host -c 1 -w 2 -- # using system's ping
0 2000 ms
0 2000 ms
0 2000 ms

-- Net::Ping->ping($host) -- # using Net::Ping
1 237.16 ms
1 197.78 ms
1 206.21 ms

-- 66.94.234.5 -- -- -- -- -- --
-- ping $host -c 1 -w 2 --
0 2000 ms
0 2000 ms
0 2000 ms

-- Net::Ping->ping($host) --
0 1259.97 ms
0 190.26 ms
1 775.19 ms
...


#cat ping.pl

#! /usr/bin/perl

use strict;
use warnings;
use threads(stack_size => 17*1024);

use Net::Ping;
use Time::HiRes qw(gettimeofday);

my $end = defined($ARGV[0]) ? $ARGV[0] : 1;


my $t_b = getMilliseconds();

threads->create(\&processPingScan, '66.94.234.' . $_) foreach ((1..$end));

while (threads->list(threads::running)) {
        sleep(1); # waiting for threads
}

my $t_e = getMilliseconds();

my $t_u = nearest(0.01, $t_e - $t_b);

print "\nDone!$t_u ms used!\n";

sub processPingScan {
        my $host = shift;
        my $temp = '';
        my $num = 3;


        $temp .= "-- ping \$host -c 1 -w 2 --\n";
        foreach ((1..$num)) {
                my ($ret, $t_u);
                if (`ping $host -c 1 -w 2` =~ /time=([\d\.]+)/) {
                        $ret = 1;
                        $t_u = $1;
                }
                else {
                        $ret = 0;
                        $t_u = 2000;
                }
                $temp .= "\t$ret\t$t_u ms\n";
        }

        $temp .= "\n-- Net::Ping->ping(\$host) --\n";
        my $oPing = Net::Ping->new('icmp', 2);
        foreach ((1..$num)) {
                my $t_b = getMilliseconds();
                my $ret = $oPing->ping($host);
                my $t_e = getMilliseconds();
                my $t_u = nearest(0.01, $t_e - $t_b);
                $temp .= "\t$ret\t$t_u ms\n";
        }

        print "-- $host -- -- -- -- -- --\n$temp\n";
        threads->detach();
        threads->exit();
}

sub getMilliseconds {
        my ($sec, $usec) = gettimeofday();
        return $sec*1000 + $usec/1000;
}

sub nearest { # nearest(0.01, 1.123) = 1.12
        my ($target, $num) = @_;
        my $x;

        $target = abs($target);

        if ($num >= 0) {
                $num = $target * int(($num + 0.5 * $target) / $target);
        }
        else {
                $num = $target * int(($num - 0.5 * $target) / $target);
        }
        return $num;
}
Subject: Re: [rt.cpan.org #31697] When using multi-threads, it will return with fault.
Date: Wed, 19 Dec 2007 08:41:48 -0600
To: bug-Net-Ping@rt.cpan.org
From: "Steve Peters" <steve@fisharerojo.org>
What version of Net::Ping are you using? Steve On Dec 19, 2007 5:47 AM, Kinpoo via RT <bug-Net-Ping@rt.cpan.org> wrote:
Show quoted text
> > Wed Dec 19 06:47:08 2007: Request 31697 was acted upon. > Transaction: Ticket created by kinpoo@gmail.com > Queue: Net-Ping > Subject: When using multi-threads, it will return with fault. > Broken in: (no value) > Severity: (no value) > Owner: Nobody > Requestors: kinpoo@gmail.com > Status: new > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=31697 > > > > When using multi-threads, it will return with fault. > > #./ ping.pl 255 > ... > -- 66.94.234.14 -- -- -- -- -- -- > -- ping $host -c 1 -w 2 -- # using system's ping > 0 2000 ms > 0 2000 ms > 0 2000 ms > > -- Net::Ping->ping($host) -- # using Net::Ping > 1 237.16 ms > 1 197.78 ms > 1 206.21 ms > > -- 66.94.234.5 -- -- -- -- -- -- > -- ping $host -c 1 -w 2 -- > 0 2000 ms > 0 2000 ms > 0 2000 ms > > -- Net::Ping->ping($host) -- > 0 1259.97 ms > 0 190.26 ms > 1 775.19 ms > ... > > > #cat ping.pl > > #! /usr/bin/perl > > use strict; > use warnings; > use threads(stack_size => 17*1024); > > use Net::Ping; > use Time::HiRes qw(gettimeofday); > > my $end = defined($ARGV[0]) ? $ARGV[0] : 1; > > > my $t_b = getMilliseconds(); > > threads->create(\&processPingScan, '66.94.234.' . $_) foreach ((1..$end)); > > while (threads->list(threads::running)) { > sleep(1); # waiting for threads > } > > my $t_e = getMilliseconds(); > > my $t_u = nearest(0.01, $t_e - $t_b); > > print "\nDone!$t_u ms used!\n"; > > sub processPingScan { > my $host = shift; > my $temp = ''; > my $num = 3; > > > $temp .= "-- ping \$host -c 1 -w 2 --\n"; > foreach ((1..$num)) { > my ($ret, $t_u); > if (`ping $host -c 1 -w 2` =~ /time=([\d\.]+)/) { > $ret = 1; > $t_u = $1; > } > else { > $ret = 0; > $t_u = 2000; > } > $temp .= "\t$ret\t$t_u ms\n"; > } > > $temp .= "\n-- Net::Ping->ping(\$host) --\n"; > my $oPing = Net::Ping->new('icmp', 2); > foreach ((1..$num)) { > my $t_b = getMilliseconds(); > my $ret = $oPing->ping($host); > my $t_e = getMilliseconds(); > my $t_u = nearest(0.01, $t_e - $t_b); > $temp .= "\t$ret\t$t_u ms\n"; > } > > print "-- $host -- -- -- -- -- --\n$temp\n"; > threads->detach(); > threads->exit(); > } > > sub getMilliseconds { > my ($sec, $usec) = gettimeofday(); > return $sec*1000 + $usec/1000; > } > > sub nearest { # nearest(0.01, 1.123) = 1.12 > my ($target, $num) = @_; > my $x; > > $target = abs($target); > > if ($num >= 0) { > $num = $target * int(($num + 0.5 * $target) / $target); > } > else { > $num = $target * int(($num - 0.5 * $target) / $target); > } > return $num; > } > > > When using multi-threads, it will return with fault. > > #./ ping.pl 255 > ... > -- 66.94.234.14 -- -- -- -- -- -- > -- ping $host -c 1 -w 2 -- # using system's ping > 0 2000 ms > 0 2000 ms > 0 2000 ms > > -- Net::Ping->ping($host) -- # using Net::Ping > 1 237.16 ms > 1 197.78 ms > 1 206.21 ms > > -- 66.94.234.5 -- -- -- -- -- -- > -- ping $host -c 1 -w 2 -- > 0 2000 ms > 0 2000 ms > 0 2000 ms > > -- Net::Ping->ping($host) -- > 0 1259.97 ms > 0 190.26 ms > 1 775.19 ms > ... > > > #cat ping.pl > > #! /usr/bin/perl > > use strict; > use warnings; > use threads(stack_size => 17*1024); > > use Net::Ping; > use Time::HiRes qw(gettimeofday); > > my $end = defined($ARGV[0]) ? $ARGV[0] : 1; > > > my $t_b = getMilliseconds(); > > threads->create(\&processPingScan, '66.94.234.' . $_) foreach ((1..$end)); > > while (threads->list(threads::running)) { > sleep(1); # waiting for threads > } > > my $t_e = getMilliseconds(); > > my $t_u = nearest(0.01, $t_e - $t_b); > > print "\nDone!$t_u ms used!\n"; > > sub processPingScan { > my $host = shift; > my $temp = ''; > my $num = 3; > > > $temp .= "-- ping \$host -c 1 -w 2 --\n"; > foreach ((1..$num)) { > my ($ret, $t_u); > if (`ping $host -c 1 -w 2` =~ /time=([\d\.]+)/) { > $ret = 1; > $t_u = $1; > } > else { > $ret = 0; > $t_u = 2000; > } > $temp .= "\t$ret\t$t_u ms\n"; > } > > $temp .= "\n-- Net::Ping->ping(\$host) --\n"; > my $oPing = Net::Ping->new('icmp', 2); > foreach ((1..$num)) { > my $t_b = getMilliseconds(); > my $ret = $oPing->ping($host); > my $t_e = getMilliseconds(); > my $t_u = nearest(0.01, $t_e - $t_b); > $temp .= "\t$ret\t$t_u ms\n"; > } > > print "-- $host -- -- -- -- -- --\n$temp\n"; > threads->detach(); > threads->exit(); > } > > sub getMilliseconds { > my ($sec, $usec) = gettimeofday(); > return $sec*1000 + $usec/1000; > } > > sub nearest { # nearest(0.01, 1.123) = 1.12 > my ($target, $num) = @_; > my $x; > > $target = abs($target); > > if ($num >= 0) { > $num = $target * int(($num + 0.5 * $target) / $target); > } > else { > $num = $target * int(($num - 0.5 * $target) / $target); > } > return $num; > } >
Subject: Re: [rt.cpan.org #31697] When using multi-threads, it will return with fault.
Date: Thu, 20 Dec 2007 10:13:10 +0800
To: bug-Net-Ping@rt.cpan.org
From: Kinpoo <kinpoo@gmail.com>

Dear Steve,

I'm using perl 5.8.5, Net::Ping 2.31 and 2.33, threads 1.67.


On 12/19/07, steve@fisharerojo.org via RT <bug-Net-Ping@rt.cpan.org> wrote:
Show quoted text

<URL: http://rt.cpan.org/Ticket/Display.html?id=31697 >

What version of Net::Ping are you using?

Steve

From: crsthn@ibest.com.br
Hi, I'm have problem with threads too. My Net::Ping is 2.31. In Dump of packets, I see field SEQ never change. And this is the problem with threads. My solution is: --- Ping.pm.orig 2008-07-22 16:25:39.465715986 -0300 +++ Ping.pm 2008-07-22 16:51:16.317763237 -0300 @@ -430,7 +430,8 @@ $from_msg # ICMP message ); - $self->{"seq"} = ($self->{"seq"} + 1) % 65536; # Increment sequence + #$self->{"seq"} = ($self->{"seq"} + 1) % 65536; # Increment sequence + $self->{"seq"} = ($self->{"seq"} + int(rand(1024))) % 65536; # Increment sequence $checksum = 0; # No checksum for starters $msg = pack(ICMP_STRUCT . $self->{"data_size"}, ICMP_ECHO, SUBCODE, $checksum, $self->{"pid"}, $self->{"seq"}, $self->{"data"}); Thanks! Cristhiano Em Qua. Dez. 19 21:13:29 2007, kinpoo@gmail.com escreveu:
Show quoted text
> Dear Steve, > > I'm using perl 5.8.5, Net::Ping 2.31 and 2.33, threads 1.67. > > On 12/19/07, steve@fisharerojo.org via RT <bug-Net-Ping@rt.cpan.org>
wrote:
Show quoted text
> > > > > > <URL: http://rt.cpan.org/Ticket/Display.html?id=31697 > > > > > What version of Net::Ping are you using? > > > > Steve > >
From: < viliam dot pucik at gmail dot com >
Hello, problem with Cristhiano solution is that two or more threads can still have the same sequence when they are generated by a random number generator. IMHO better solution is to specify uniq offset and max numbers for every thread (via set_thread) where Net::Ping is used: $THREADS_MAX = 10; ... my $ping = new Net::Ping( "icmp" ); # the uniq sequence number for each thread is now calculated as: # [ threads->tid() + $THREADS_MAX * number_of_send_PINGs_in_the_thread ] $ping->set_thread( threads->tid(), $THREADS_MAX ); ... To use "set_thread" you need to apply the "set_thread.patch" patch. Hope this helps. Viliam On Tue Jul 22 16:30:02 2008, cristhiano wrote:
Show quoted text
> Hi, > > I'm have problem with threads too. My Net::Ping is 2.31. In Dump of > packets, I see field SEQ never change. And this is the problem with
threads.
Show quoted text
> > My solution is: > > --- Ping.pm.orig 2008-07-22 16:25:39.465715986 -0300 > +++ Ping.pm 2008-07-22 16:51:16.317763237 -0300 > @@ -430,7 +430,8 @@ > $from_msg # ICMP message > ); > > - $self->{"seq"} = ($self->{"seq"} + 1) % 65536; # Increment sequence > + #$self->{"seq"} = ($self->{"seq"} + 1) % 65536; # Increment
sequence
Show quoted text
> + $self->{"seq"} = ($self->{"seq"} + int(rand(1024))) % 65536; # > Increment sequence > $checksum = 0; # No checksum for starters > $msg = pack(ICMP_STRUCT . $self->{"data_size"}, ICMP_ECHO, SUBCODE, > $checksum, $self->{"pid"}, $self->{"seq"}, $self->
{"data"});
Show quoted text
> > Thanks! > Cristhiano
Subject: set_thread.patch
--- Ping.pm.org 2010-03-26 23:06:51.346739372 +0100 +++ Ping.pm 2010-03-27 21:12:35.075014549 +0100 @@ -128,6 +128,9 @@ sub new $self->{"econnrefused"} = undef; # Default Connection refused behavior $self->{"seq"} = 0; # For counting packets + $self->{"thread"} = 0; # Used for fixing "seq" when executing in threads + $self->{"thread_max"} = 1; # Used for fixing "seq" when executing in threads + $self->{"count"} = 0; # Used for fixing "seq" when executing in threads if ($self->{"proto"} eq "udp") # Open a socket { $self->{"proto_num"} = (getprotobyname('udp'))[2] || @@ -201,6 +204,16 @@ sub new return($self); } +# Every thread will have its own uniq sequences calculated as +# [ seq = thread + thread_max * count ] +# where count is the number of send pings +sub set_thread { + my ( $self, $thread, $thread_max ) = @_; + + $self->{"thread"} = $thread; + $self->{"thread_max"} = $thread_max; +} + # Description: Set the local IP address from which pings will be sent. # For ICMP and UDP pings, this calls bind() on the already-opened socket; # for TCP pings, just saves the address to be used when the socket is @@ -443,7 +456,10 @@ sub ping_icmp $from_msg # ICMP message ); - $self->{"seq"} = ($self->{"seq"} + 1) % 65536; # Increment sequence + #$self->{"seq"} = ($self->{"seq"} + 1) % 65536; # Increment sequence + $self->{"seq"} = ( $self->{"thread"} + $self->{"thread_max"} * $self->{"count"} ) % 65536; # Increment sequence + $self->{"count"}++; # Increment number of send PINGs + $checksum = 0; # No checksum for starters $msg = pack(ICMP_STRUCT . $self->{"data_size"}, ICMP_ECHO, SUBCODE, $checksum, $self->{"pid"}, $self->{"seq"}, $self->{"data"});


This service runs on Request Tracker, is sponsored by The Perl Foundation, and maintained by Best Practical Solutions.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.