Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timeout bug in inactive handle #583

Closed
omriyaacovi opened this issue Dec 27, 2018 · 2 comments
Closed

Timeout bug in inactive handle #583

omriyaacovi opened this issue Dec 27, 2018 · 2 comments
Assignees
Labels

Comments

@omriyaacovi
Copy link

When reading packet data from an activated inactive handle to read packets off the wire, a positive timeout seems to be blocking forever.
Consider this code segment:

package main

import (
	"log"
	"time"

	"github.com/google/gopacket/pcap"
)

var (
	device  = "eno1"
	snaplen = 65535
	promisc = true
)

// A simple ZeroCopyReadPacketData() on a handle generated with gopacket.OpenLive()
func openLive() {
	handle, err := pcap.OpenLive(device, int32(snaplen), promisc, time.Second*2)
	if err != nil {
		log.Fatal(err)
	}
	err = handle.SetBPFFilter("src host 1.2.3.4") // A random filter to make sure no data is received
	if err != nil {
		log.Fatal(err)
	}
	data, _, err := handle.ZeroCopyReadPacketData()
	if err != nil {
		log.Fatal(err)
	}
	log.Println(data)
}

// A simple ZeroCopyReadPacketData() on a handle generated from an InactiveHandle
func inactive() {
	inactiveHandle, err := pcap.NewInactiveHandle(device)
	err = inactiveHandle.SetSnapLen(snaplen)
	if err != nil {
		log.Fatal(err)
	}
	err = inactiveHandle.SetPromisc(promisc)
	if err != nil {
		log.Fatal(err)
	}
	err = inactiveHandle.SetTimeout(time.Second * 2)
	if err != nil {
		log.Fatal(err)
	}
	handle, err := inactiveHandle.Activate()
	if err != nil {
		log.Fatal(err)
	}
	err = handle.SetBPFFilter("src host 1.2.3.4") // A random filter to make sure no data is received
	if err != nil {
		log.Fatal(err)
	}
	data, _, err := handle.ZeroCopyReadPacketData()
	if err != nil {
		log.Fatal(err)
	}
	log.Println(data)
}

With this main function:

func main() {
	log.Println("Started")
	openLive()
}

Will work just fine - output:

2018/12/27 00:00:02 started
2018/12/27 00:00:05 Timeout Expired

Whereas with this main function, calling inactive() instead of openLive():

func main() {
	log.Println("Started")
	inactive()
}

Will just hang/block forever (until killed):

2018/12/27 00:00:02 started

The same thing will happen if we replace ZeroReadPacketData() with ReadPacketData()
I've set timeout in both functions to two seconds.

@notti notti added the bug label Jan 5, 2019
@notti notti self-assigned this Jan 5, 2019
@notti
Copy link
Collaborator

notti commented Jan 5, 2019

Could verify the behaviour. The reason why openLive works is, that OpenLive sets pcap to nonblocking and the waiting is done with pcap_wait (I think this was done because of a performance regression). The same mechanism wasn't included in Activate (no idea why).
strace shows that libpcap seems to want wo wait forever (poll([{fd=3, events=POLLIN}], 1, -1).
If I remove nonblocking from OpenLive it shows the same behaviour (adding to Activate removes it).

I'll investigate what the root cause is (=why libpcap doesn't want to wait 2 seconds).

@notti
Copy link
Collaborator

notti commented Jan 5, 2019

Hmm ok my bad: pcap_wait was introduced to counter this (in #253) - not due to performance regression

@notti notti closed this as completed in e022c61 Jan 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants