-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Deadlock when trying to quit #253
Copy link
Copy link
Closed
Description
This program will deadlock with the latest version of libpcap (1.8.1):
package main
import (
"log"
"os"
"os/exec"
"os/signal"
"time"
"github.com/google/gopacket/pcap"
)
// Tap is the name of the tap we'll capture traffic from, shouldn't exist
// already otherwise the ip command will fail
const Tap = "testtap"
func main() {
// Create tap that won't receive any traffic, ever
cmd := exec.Command("ip", "tuntap", "add", "mode", "tap", Tap)
if _, err := cmd.CombinedOutput(); err != nil {
panic(err)
}
cmd = exec.Command("ip", "link", "set", Tap, "up")
if _, err := cmd.CombinedOutput(); err != nil {
panic(err)
}
// And delete it when we're done
defer func() {
cmd := exec.Command("ip", "link", "del", Tap)
if _, err := cmd.CombinedOutput(); err != nil {
panic(err)
}
}()
// Channel to signal when the pcap reading goroutine is finished
done := make(chan bool)
handle, err := pcap.OpenLive(Tap, 1600, true, time.Second)
if err != nil {
panic(err)
}
go func() {
defer close(done)
var err error
for err == nil {
_, _, err = handle.ReadPacketData()
if err == pcap.NextErrorTimeoutExpired {
// non-terminating...
err = nil
}
}
log.Printf("done reading packets: %v", err)
}()
// Wait for Ctrl-C
sig := make(chan os.Signal, 1024)
signal.Notify(sig, os.Interrupt)
<-sig
log.Print("got SIGTERM, closing handle")
// Close the handle
handle.Close()
// Wait for goroutine to terminate
<-done
log.Print("all done")
}
Expected output (with libpcap 1.7.4):
$ sudo ./test
^C2016/11/09 14:36:22 got SIGTERM, closing handle
2016/11/09 14:36:23 done reading packets: EOF
2016/11/09 14:36:23 all done
Actual output (with libpcap 1.8.1):
$ sudo ./test
^C2016/11/09 14:36:22 got SIGTERM, closing handle
<hangs>
The problem is related to the read timeout with pcap_next_ex: [0]
This means that the read timeout should NOT be used, for example, in an interactive application to allow the packet capture loop to ``poll'' for user input periodically, as there's no guarantee that a call reading packets will return after the timeout expires even if no packets have arrived.
pcap.Handle.Close should probably call pcap_breakloop in order to signal that pcap_next_ex should return. I looked at the pcap code and there may need to be some refactoring of the locking to allow for this.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels