From 05c713d22a325852bfd0d1d8dc730e5a06902abc Mon Sep 17 00:00:00 2001 From: david Date: Thu, 5 Apr 2012 03:30:09 +0000 Subject: [PATCH] Don't try to do FD_ISSET on a nonselectable pcap descriptor. The Nsock select engine stores readiness information in a mask instead of doing an FD_ISSET against the descriptor every time. This is a good idea, but it removed a special case in the pre-engines code: in case PCAP_CAN_DO_SELECT is not defined, we can't do FD_ISSET on the descriptor because it is -1. Here we check for that occurrence and set EV_READ in the mask so that a non-blocking pcap read can happen every iteration. --- nsock/src/engine_select.c | 60 +++++++++++++++++++++++++-------------- nsock/src/nsock_core.c | 5 +--- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/nsock/src/engine_select.c b/nsock/src/engine_select.c index ee222d45d..c222a7ad8 100644 --- a/nsock/src/engine_select.c +++ b/nsock/src/engine_select.c @@ -349,12 +349,47 @@ int select_loop(mspool *nsp, int msec_timeout) { /* ---- INTERNAL FUNCTIONS ---- */ +static int get_evmask(const mspool *nsp, const msiod *nsi) { + struct select_engine_info *sinfo = (struct select_engine_info *)nsp->engine_data; + int sd, evmask; + + evmask = EV_NONE; + +#if HAVE_PCAP +#ifndef PCAP_CAN_DO_SELECT + if (nsi->pcap) { + /* Always assume readable for a non-blocking read. We can't check FD_ISSET + because we don't have a pcap_desc. */ + evmask |= EV_READ; + return evmask; + } +#endif +#endif + +#if HAVE_PCAP + if (nsi->pcap) + sd = ((mspcap *)nsi->pcap)->pcap_desc; + else +#endif + sd = nsi->sd; + + assert(sd >= 0); + + if (FD_ISSET(sd, &sinfo->fds_results_r)) + evmask |= EV_READ; + if (FD_ISSET(sd, &sinfo->fds_results_w)) + evmask |= EV_WRITE; + if (FD_ISSET(sd, &sinfo->fds_results_x)) + evmask |= EV_EXCEPT; + + return evmask; +} + /* Iterate through all the event lists (such as connect_events, read_events, * timer_events, etc) and take action for those that have completed (due to * timeout, i/o, etc) */ void iterate_through_event_lists(mspool *nsp) { gh_list_elem *current, *next, *last, *timer_last; - struct select_engine_info *sinfo = (struct select_engine_info *)nsp->engine_data; /* Clear it -- We will find the next event as we go through the list */ nsp->next_ev.tv_sec = 0; @@ -366,27 +401,8 @@ void iterate_through_event_lists(mspool *nsp) { current != NULL && GH_LIST_ELEM_PREV(current) != last; current = next) { msiod *nsi = (msiod *)GH_LIST_ELEM_DATA(current); - if (nsi->state != NSIOD_STATE_DELETED && nsi->events_pending) { - int sd, evmask = EV_NONE; - -#if HAVE_PCAP - if (nsi->pcap) - sd = ((mspcap *)nsi->pcap)->pcap_desc; - else -#endif - sd = nsi->sd; - - assert(sd >= 0); - - if (FD_ISSET(sd, &sinfo->fds_results_r)) - evmask |= EV_READ; - if (FD_ISSET(sd, &sinfo->fds_results_w)) - evmask |= EV_WRITE; - if (FD_ISSET(sd, &sinfo->fds_results_x)) - evmask |= EV_EXCEPT; - - process_iod_events(nsp, nsi, evmask); - } + if (nsi->state != NSIOD_STATE_DELETED && nsi->events_pending) + process_iod_events(nsp, nsi, get_evmask(nsp, nsi)); next = GH_LIST_ELEM_NEXT(current); if (nsi->state == NSIOD_STATE_DELETED) { diff --git a/nsock/src/nsock_core.c b/nsock/src/nsock_core.c index 3be9ce886..1ca1c8450 100644 --- a/nsock/src/nsock_core.c +++ b/nsock/src/nsock_core.c @@ -982,10 +982,7 @@ void process_event(mspool *nsp, gh_list *evlist, msevent *nse, int ev) { if (nsp->tracelevel > 5) nsock_trace(nsp, "PCAP iterating %lu", nse->id); -#if PCAP_CAN_DO_SELECT - if (ev & EV_READ) -#endif - { + if (ev & EV_READ) { /* buffer empty? check it! */ if (FILESPACE_LENGTH(&(nse->iobuf)) == 0) do_actual_pcap_read(nse);