From: Guy Harris Date: Mon, 12 Oct 2009 23:24:57 +0000 (-0700) Subject: In pcap_read_linux_mmap(), if there are no frames available, call poll() X-Git-Tag: libpcap-1.1.0~67 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/bf7491046a6123f40be6993a24a61e9525a44666 In pcap_read_linux_mmap(), if there are no frames available, call poll() even if we're in non-blocking mode, to pick up any error indications - in that case, use a timeout of 0, so poll() doesn't block. Don't test individual exceptional-condition bits in the poll() return unless one of them is set, so we just do one test in the typical (no exceptional condition) case. --- diff --git a/pcap-linux.c b/pcap-linux.c index 8356ba54..48cad3aa 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -2929,42 +2929,47 @@ pcap_get_ring_frame(pcap_t *handle, int status) return h.raw; } +#ifndef POLLRDHUP +#define POLLRDHUP 0 +#endif + static int pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { + int timeout; int pkts = 0; char c; /* wait for frames availability.*/ - if ((handle->md.timeout >= 0) && - !pcap_get_ring_frame(handle, TP_STATUS_USER)) { + if (!pcap_get_ring_frame(handle, TP_STATUS_USER)) { struct pollfd pollinfo; int ret; pollinfo.fd = handle->fd; pollinfo.events = POLLIN; + if (handle->md.timeout == 0) + timeout = -1; /* block forever */ + else if (handle->md.timeout > 0) + timeout = handle->md.timeout; /* block for that amount of time */ + else + timeout = 0; /* non-blocking mode - poll to pick up errors */ do { - /* poll() requires a negative timeout to wait forever */ - ret = poll(&pollinfo, 1, (handle->md.timeout > 0)? - handle->md.timeout: -1); - if ((ret < 0) && (errno != EINTR)) { + ret = poll(&pollinfo, 1, timeout); + if (ret < 0 && errno != EINTR) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't poll on packet socket: %s", pcap_strerror(errno)); return PCAP_ERROR; - } else if (ret > 0) { + } else if (ret > 0 && + (pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) { /* - * There's some indication on the descriptor. - * Check for indications other than - * "you can read on this descriptor". + * There's some indication other than + * "you can read on this descriptor" on + * the descriptor. */ -#ifdef POLLRDHUP if (pollinfo.revents & (POLLHUP | POLLRDHUP)) { -#else - if (pollinfo.revents & POLLHUP) { -#endif snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Hangup on packet socket");