I have a GUI program that allows a user a scan a network, the issue is that when the pcap_loop function is called, my GUI program becomes unresponsive.(the pcap_loop blocks the current thread).
When i try to use pthreads, i got a SIGSEGV fault at the pcap_loop function.Why?It's as if the thread can't see the procPacket function itself.
void procPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{
//show packets here
}
void* pcapLooper(void* param)
{
pcap_t* handler = (pcap_t*) param;
pcap_loop(handler, 900 开发者_C百科,procPacket, NULL );
}
//some function that runs when a button is pressed
//handler has been opened through pcap_open_live
pthread_t scanner;
int t = pthread_create(&scanner,NULL,&pcapLooper, &handler );
if(t)
{
std::cout << "failed" << std::endl;
}
pthread_join(scanner,NULL);
//do other stuff.
I would strongly suggest not using threads unless you absolutely have to.
The problem is that you have to be extremely careful to avoid race conditions and other synchronisation problems. For instance, your GUI framework library is probably not expecting to be called from multiple threads, and so your //show packets here
routine may confuse it a lot.
Instead I would suggest, if possible, reading the packets from the main thread. You don't say which GUI framework you're using; since you're using C++ I'll assume Qt since that's quite common, but all other frameworks have similar functionality.
What you need to do is:
- Call pcap_setnonblock() to put the capture descriptor in non-blocking mode
- Call pcap_get_selectable_fd() to get a file descriptor to monitor for events
- Use a QSocketNotifier object (passing the file descriptor from the previous step as the socket parameter) to monitor the file descriptor for events
- When the event fires, call pcap_dispatch() to dispatch packets
- For maximum portability, also call pcap_dispatch() on a timer, because select() doesn't work well on pcap sockets on some OSs.
(As to why your code is currently crashing - note that you probably want to pass handler
rather than &handler
as the parameter to pthread_create()
. But just fixing that may lead to strange unreliability later - so going single-threaded is almost certainly the way forward!)
You need much less "&"s. Assuming
pcap_t *handle = pcap_open_live(...);
using &handle
will be of type pcap_t **
, but your thread function casts it back (the cast by the way is also pointless/redundant) to pcap_t *
, which leads to undefined behavior when using it, and is usually going to go wrong. Better:
static void *pcap_looper(void *arg) { pcap_t *handle = arg; /* etc. */ return NULL; } int main(void) { pcap_t *handle; pthread_t tid; int ret; handle = pcap_open_live(...); ret = pthread_create(&tid, NULL, pcap_looper, handle); ... pthread_join(tid, NULL); return EXIT_SUCCESS; }
精彩评论