bph
bph

Reputation: 11258

How to return from pcap_loop() or pcap_dispatch() without using pcap_breakloop() within the callback function

If you use blocking pcap_loop() or pcap_dispatch() to handle incoming packet data via a suitable callback fn you may have a requirement to break out of those functions, i.e. get them to return.

Now pcap_breakloop() is a means to do this, but that doesn't work if you call it from another thread of execution. You can call pcap_breakloop() from within the callback fn specified in pcap_loop()/pcap_dispatch() but this is only an option if you can guarantee a pkt is going to trigger the callback.

How can one break a pcap_loop() or pcap_dispatch() in the absence of an incoming packet to trigger the callback fn?

If pcap_loop()/pcap_dispatch() is blocked in this use-case scenario, then you're going to want to unblock it from a different thread. But you can't call pcap_breakloop() from a different thread of execution.

I read the man page and it mentioned something about using signals, but these are non-portable OS specific.

The only work-around I can see to this problem is using pcap_dispatch() but in unblocking mode (pcap_setnonblock()). You can then put pcap_dispatch() in a tight while-loop. This works but I think it would be more elegant to be able to politely ask pcap_loop() or pcap_dispatch() to return from another thread?

Upvotes: 4

Views: 2764

Answers (1)

user12341203
user12341203

Reputation: 109

How can one break a pcap_loop() or pcap_dispatch() in the absence of an incoming packet to trigger the callback fn?

On UN*Xes, catch a signal such as SIGUSR1, have the signal handler do nothing, and, after calling pcap_breakloop(), call pthread_kill() to send that signal to the thread that's doing the pcap_dispatch() or pcap_loop(). When you catch the signal, do not specify SA_RESTART; that way, the signal will interrupt system calls such as the call made by libpcap to read the captured packets. That's UN*X-specific, but it's not specific to particular versions of UN*X.

On Windows, use pcap_getevent() to get the "event handle for the pcap_t, and use SetEvent() on that handle after calling pcap_breakloop().

Upvotes: 3

Related Questions