Skip Menu |

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

Report information
The Basics
Id: 100269
Status: resolved
Worked: 5 min
Priority: 0/
Queue: Net-Pcap-Easy

People
Owner: jettero [...] cpan.org
Requestors: sup2000 [...] hotmail.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 1.4207
Fixed in: (no value)



Subject: Timeout doesn't seem to work
If I run the attached perl code, I get inconsistent looping behavior. I've set the timeout to 1000 msec, should should be 1 second. But, I'm finding that, the timeout doesn't return (all examples end with my hitting ctrl+c): scott@newluke [~/tmp]# time sudo perl show-pcap.pl Tue Nov 11 08:46:13 2014.13363 entering loop real 0m33.055s user 0m0.030s sys 0m0.013s scott@newluke [~/tmp]# Now, if I send it a single packet, the loop returns, as expected, but it doesn't start respecting timeouts: scott@newluke [~/tmp]# time sudo perl show-pcap.pl Tue Nov 11 08:47:12 2014.819306 entering loop Tue Nov 11 08:47:16 2014.814889 Got a packet Tue Nov 11 08:47:16 2014.814934 Looping Tue Nov 11 08:47:16 2014.815024 Got a packet Tue Nov 11 08:47:16 2014.815049 Looping real 0m15.034s user 0m0.029s sys 0m0.011s scott@newluke [~/tmp]# The behavior I'm observing here is consistent with the pcap man page that suggests that timeout doesn't work consistently across various operating systems, and it seems like it's something that libpcap doesn't consider a bug: https://github.com/the-tcpdump-group/libpcap/issues/86 This sort of behavior makes it challenging to build a single threaded, interactive perl script using Net::Pcap::Easy. Is this a known shortcoming on Net::Pcap::Easy, a bug, or am I approaching this wrong?
Subject: show-pcap.pl
#!/usr/local/bin/perl use strict; use warnings; use Net::Pcap::Easy; use Time::HiRes; my $npe = Net::Pcap::Easy->new( 'dev' => 'eth0', 'filter' => 'host 198.176.29.35 and icmp', 'packets_per_loop' => 1, 'timeout_in_ms' => 1000, #1 second 'promiscuous' => 0, 'icmp_callback' => \&got_a_packet ); print timestamp()." entering loop\n"; while( $npe->loop ) { print timestamp()." Looping\n"; } sub got_a_packet { print timestamp()." Got a packet\n"; } sub timestamp { my ( $sec, $usec ) = Time::HiRes::gettimeofday(); return localtime().".$usec"; }
Hi! The timeout used by Pcap::Easy is really the timeout in the upstream package Net::Pcap. That package just uses the libpcap functions. I think I maybe misread the upstream docs. I'm using pcap_open_live() which states: "The $to_ms parameter specifies a read timeout in milliseconds." I was never really clear if they mean the open timeout or the read timeout. If they mean the open timeout, why use the "read" verbage? I saw other sourcecode samples where people made the similar assumption. I also believe I've seen it work some places and not others. In short: I think this is a libpcap bug. I'm pretty sure the timeout only works on really old versions or the very very latest versions. I will try to do some testing on my Archlinux box and a really old ubuntu box and see if I get different results. -Paul On Tue Nov 11 09:54:15 2014, sup2000@hotmail.com wrote: Show quoted text
> If I run the attached perl code, I get inconsistent looping behavior. > I've set the timeout to 1000 msec, should should be 1 second. But, I'm > finding that, the timeout doesn't return (all examples end with my > hitting ctrl+c): > > scott@newluke [~/tmp]# time sudo perl show-pcap.pl > Tue Nov 11 08:46:13 2014.13363 entering loop > > > real 0m33.055s > user 0m0.030s > sys 0m0.013s > scott@newluke [~/tmp]# > > Now, if I send it a single packet, the loop returns, as expected, but > it doesn't start respecting timeouts: > > scott@newluke [~/tmp]# time sudo perl show-pcap.pl > Tue Nov 11 08:47:12 2014.819306 entering loop > Tue Nov 11 08:47:16 2014.814889 Got a packet > Tue Nov 11 08:47:16 2014.814934 Looping > Tue Nov 11 08:47:16 2014.815024 Got a packet > Tue Nov 11 08:47:16 2014.815049 Looping > > > real 0m15.034s > user 0m0.029s > sys 0m0.011s > scott@newluke [~/tmp]# > > The behavior I'm observing here is consistent with the pcap man page > that suggests that timeout doesn't work consistently across various > operating systems, and it seems like it's something that libpcap > doesn't consider a bug: > > https://github.com/the-tcpdump-group/libpcap/issues/86 > > This sort of behavior makes it challenging to build a single threaded, > interactive perl script using Net::Pcap::Easy. > > Is this a known shortcoming on Net::Pcap::Easy, a bug, or am I > approaching this wrong?
-- If riding in an airplane is flying, then riding in a boat is swimming. 116 jumps, 48.6 minutes of freefall, 92.9 freefall miles.
OIC. I did not read your message correctly at all. Now that I'm caught up on my various conference calls … Yeah, I was pretty sure this was a known problem. So, disgregard everything I said above. I should probably just take the timeout language out of the pod now that I've read that github link. The way you'd handle this in an interactive program is just go ahead and let Pcap block forever and use forks or signals. POE has a Wheel for blocking single threaded things (and this direction is highly recommended if you can use POE). I also sometimes use forks … use strict; use warnings; use forks; # better than threads, but compatible by design use forks::shared; # for the worker info my @worker_scalars : shared; my $blocking_pcap_thread = threads->new(sub{ # PCAP THINGS HERE push @worker_scalars, "careful what you put in here btw"; }); my $ui_thread = threads->new(sub{ # user interface stuff here if( @worker_scalars ) { say $_ for @worker_scalars } }); $_->join for threads->list; -- If riding in an airplane is flying, then riding in a boat is swimming. 116 jumps, 48.6 minutes of freefall, 92.9 freefall miles.
From: sup2000 [...] hotmail.com
I've gone down the path of forks and I'm really happy with how it's turning it, gee, I should've tried this sooner! I was thinking about proposing a change like this: http://www.perlmonks.org/?node_id=1079954 but it seems to me to only make sense when packets_per_loop == 1, which I'm assuming isn't the typical use case of Net::Pcap::Easy. I'm with you on the docs change, I've submitted a pull request with a proposed docs change. I'm assuming you wanted to leave this as an undocumented parameter. I can amend the pull request if you wanted to go a different direction. Thanks!
On Mon Nov 17 00:58:07 2014, sup2000@hotmail.com wrote: Show quoted text
> I've gone down the path of forks and I'm really happy with how it's > turning it, gee, I should've tried this sooner!
I fixed the docs and added a forks example. Show quoted text
> but it seems to me to only make sense when packets_per_loop == 1, > which I'm assuming isn't the typical use case of Net::Pcap::Easy.
It's entirely a matter of opinion. I tend to write event based programs with Pcap::Easy. For those, I use packets_per_loop=>1 so the actions happen right away. But I've also written network analyzers that look for certain types of traffic and update counters … for those you really want the ppl nice and high so pcap spends more overall time sitting on the wire. It helps if you're multi-threaded (multiprocess with forks) so you do your packet analysis in a separate thread. Depending on the amount of packets and work, I might even use DB_File to spool to disk. (Past a certain point, the overhead of calling a perl sub just isn't worth it and I drop to C). Show quoted text
> I'm with you on the docs change, I've submitted a pull request with a > proposed docs change. I'm assuming you wanted to leave this as an > undocumented parameter. I can amend the pull request if you wanted to > go a different direction.
Oh, thanks for this!! I already fixed the docs and did a release before I noticed this though. I left the option there, in case someone goes looking for a timeout specifically — one of my ideas with the "easy" part of the module was to have all the docs and examples you'd need in one big perldoc. -- If riding in an airplane is flying, then riding in a boat is swimming. 116 jumps, 48.6 minutes of freefall, 92.9 freefall miles.
1.4209 release -- If riding in an airplane is flying, then riding in a boat is swimming. 116 jumps, 48.6 minutes of freefall, 92.9 freefall miles.