コード例 #1
0
ファイル: comm_select.c プロジェクト: carriercomm/myboxfs
static void
comm_select_http_incoming(void)
{
    int nfds = 0;
    int fds[MAXHTTPPORTS];
    int j;
    int nevents;
    http_io_events = 0;
    for (j = 0; j < NHttpSockets; j++) {
	if (HttpSockets[j] < 0)
	    continue;
	if (commDeferRead(HttpSockets[j]))
	    continue;
	fds[nfds++] = HttpSockets[j];
    }
    nevents = comm_check_incoming_select_handlers(nfds, fds);
    incoming_http_interval += Config.comm_incoming.http_average - nevents;
    if (incoming_http_interval < 0)
	incoming_http_interval = 0;
    if (incoming_http_interval > MAX_INCOMING_INTERVAL)
	incoming_http_interval = MAX_INCOMING_INTERVAL;
    if (nevents > INCOMING_HTTP_MAX)
	nevents = INCOMING_HTTP_MAX;
    statHistCount(&statCounter.comm_http_incoming, nevents);
}
コード例 #2
0
ファイル: comm_epoll.c プロジェクト: CoolerVoid/squid
static int
do_comm_select(int msec)
{
    int i;
    int num, saved_errno;

    if (epoll_fds == 0) {
	assert(shutting_down);
	return COMM_SHUTDOWN;
    }
    statCounter.syscalls.polls++;
    num = epoll_wait(kdpfd, events, MAX_EVENTS, msec);
    saved_errno = errno;
    getCurrentTime();
    debug(5, 5) ("do_comm_select: %d fds ready\n", num);
    if (num < 0) {
	if (ignoreErrno(saved_errno))
	    return COMM_OK;

	debug(5, 1) ("comm_select: epoll failure: %s\n", xstrerror());
	return COMM_ERROR;
    }
    statHistCount(&statCounter.select_fds_hist, num);

    if (num == 0)
	return COMM_TIMEOUT;

    for (i = 0; i < num; i++) {
	comm_call_handlers(events[i].data.fd, events[i].events & ~EPOLLOUT, events[i].events & ~EPOLLIN);
    }

    return COMM_OK;
}
コード例 #3
0
static int
do_comm_select(int msec)
{
    int i;
    int num;
    int fd;
    struct epoll_event *cevents;

    if (epoll_fds == 0) {
	assert(shutting_down);
	return COMM_SHUTDOWN;
    }
    statCounter.syscalls.polls++;
    num = epoll_wait(kdpfd, events, MAX_EVENTS, msec);
    if (num < 0) {
	getCurrentTime();
	if (ignoreErrno(errno))
	    return COMM_OK;

	debug(5, 1) ("comm_select: epoll failure: %s\n", xstrerror());
	return COMM_ERROR;
    }
    statHistCount(&statCounter.select_fds_hist, num);

    if (num == 0)
	return COMM_TIMEOUT;

    for (i = 0, cevents = events; i < num; i++, cevents++) {
	fd = cevents->data.fd;
	comm_call_handlers(fd, cevents->events & ~EPOLLOUT, cevents->events & ~EPOLLIN);
    }

    return COMM_OK;
}
コード例 #4
0
static void
icpCount(void *buf, int which, size_t len, int delay)
{
    icp_common_t *icp = buf;
    if (len < sizeof(*icp))
	return;
    if (SENT == which) {
	statCounter.icp.pkts_sent++;
	kb_incr(&statCounter.icp.kbytes_sent, len);
	if (ICP_QUERY == icp->opcode) {
	    statCounter.icp.queries_sent++;
	    kb_incr(&statCounter.icp.q_kbytes_sent, len);
	} else {
	    statCounter.icp.replies_sent++;
	    kb_incr(&statCounter.icp.r_kbytes_sent, len);
	    /* this is the sent-reply service time */
	    statHistCount(&statCounter.icp.reply_svc_time, delay);
	}
	if (ICP_HIT == icp->opcode)
	    statCounter.icp.hits_sent++;
    } else if (RECV == which) {
	statCounter.icp.pkts_recv++;
	kb_incr(&statCounter.icp.kbytes_recv, len);
	if (ICP_QUERY == icp->opcode) {
	    statCounter.icp.queries_recv++;
	    kb_incr(&statCounter.icp.q_kbytes_recv, len);
	} else {
	    statCounter.icp.replies_recv++;
	    kb_incr(&statCounter.icp.r_kbytes_recv, len);
	    /* statCounter.icp.query_svc_time set in clientUpdateCounters */
	}
	if (ICP_HIT == icp->opcode)
	    statCounter.icp.hits_recv++;
    }
}
コード例 #5
0
void
httpHeaderClean(HttpHeader * hdr)
{
    HttpHeaderPos pos = HttpHeaderInitPos;
    HttpHeaderEntry *e;

    assert(hdr);
    assert(hdr->owner > hoNone && hdr->owner <= hoReply);
    debug(55, 7) ("cleaning hdr: %p owner: %d\n", hdr, hdr->owner);

    /*
     * An unfortunate bug.  The hdr->entries array is initialized
     * such that count is set to zero.  httpHeaderClean() seems to
     * be called both when 'hdr' is created, and destroyed.  Thus,
     * we accumulate a large number of zero counts for 'hdr' before
     * it is ever used.  Can't think of a good way to fix it, except
     * adding a state variable that indicates whether or not 'hdr'
     * has been used.  As a hack, just never count zero-sized header
     * arrays.
     */
    if (0 != hdr->entries.count)
	statHistCount(&HttpHeaderStats[hdr->owner].hdrUCountDistr, hdr->entries.count);
    HttpHeaderStats[hdr->owner].destroyedCount++;
    HttpHeaderStats[hdr->owner].busyDestroyedCount += hdr->entries.count > 0;
    while ((e = httpHeaderGetEntry(hdr, &pos))) {
	/* tmp hack to try to avoid coredumps */
	if (e->id >= HDR_ENUM_END) {
	    debug(55, 0) ("httpHeaderClean BUG: entry[%d] is invalid (%d). Ignored.\n",
		(int) pos, e->id);
	} else {
	    statHistCount(&HttpHeaderStats[hdr->owner].fieldTypeDistr, e->id);
	    /* yes, this destroy() leaves us in an inconsistent state */
	    httpHeaderEntryDestroy(e);
	}
    }
    arrayClean(&hdr->entries);
}
コード例 #6
0
static int
do_comm_select(int msec)
{
    int num, saved_errno;
    struct timeval tv;
    fd_set readfds;
    fd_set writefds;
    fd_set errfds;
    int fd;

    if (nreadfds + nwritefds == 0) {
	assert(shutting_down);
	return COMM_SHUTDOWN;
    }
    memcpy(&readfds, &global_readfds, sizeof(fd_set));
    memcpy(&writefds, &global_writefds, sizeof(fd_set));
    memcpy(&errfds, &global_writefds, sizeof(fd_set));
    tv.tv_sec = msec / 1000;
    tv.tv_usec = (msec % 1000) * 1000;
    statCounter.syscalls.selects++;
    num = select(Biggest_FD + 1, &readfds, &writefds, &errfds, &tv);
    saved_errno = errno;
    getCurrentTime();
    debug(5, 5) ("do_comm_select: %d fds ready\n", num);
    if (num < 0) {
	if (ignoreErrno(saved_errno))
	    return COMM_OK;

	debug(5, 1) ("comm_select: select failure: %s\n", xstrerror());
	return COMM_ERROR;
    }
    statHistCount(&statCounter.select_fds_hist, num);

    if (num == 0)
	return COMM_TIMEOUT;

    for (fd = 0; fd <= Biggest_FD; fd++) {
	int read_event = FD_ISSET(fd, &readfds);
	int write_event = FD_ISSET(fd, &writefds) || FD_ISSET(fd, &errfds);
	if (read_event || write_event)
	    comm_call_handlers(fd, read_event, write_event);
    }
    return COMM_OK;
}
コード例 #7
0
static int
do_comm_select(int msec)
{
    int num;
    int i;

    if (nfds == 0) {
	assert(shutting_down);
	return COMM_SHUTDOWN;
    }
    statCounter.syscalls.selects++;
    num = poll(pfds, nfds, msec);
    if (num < 0) {
	getCurrentTime();
	if (ignoreErrno(errno))
	    return COMM_OK;

	debug(5, 1) ("comm_select: poll failure: %s\n", xstrerror());
	return COMM_ERROR;
    }
    statHistCount(&statCounter.select_fds_hist, num);

    if (num == 0)
	return COMM_TIMEOUT;

    for (i = nfds - 1; num > 0 && i >= 0; i--) {
	struct pollfd *pfd = &pfds[i];
	short read_event, write_event;

	if (!pfd->revents)
	    continue;

	read_event = pfd->revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR);
	write_event = pfd->revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR);

	pfd->revents = 0;

	comm_call_handlers(pfd->fd, read_event, write_event);
	num--;
    }

    return COMM_OK;
}
コード例 #8
0
ファイル: CacheDigest.c プロジェクト: selecli/squid
void
cacheDigestAdd(CacheDigest * cd, const cache_key * key)
{
	assert(cd && key);
	/* hash */
	cacheDigestHashKey(cd, key);
	/* turn on corresponding bits */
#if CD_FAST_ADD
	CBIT_SET(cd->mask, hashed_keys[0]);
	CBIT_SET(cd->mask, hashed_keys[1]);
	CBIT_SET(cd->mask, hashed_keys[2]);
	CBIT_SET(cd->mask, hashed_keys[3]);
#else
	{
		int on_xition_cnt = 0;
		if (!CBIT_TEST(cd->mask, hashed_keys[0]))
		{
			CBIT_SET(cd->mask, hashed_keys[0]);
			on_xition_cnt++;
		}
		if (!CBIT_TEST(cd->mask, hashed_keys[1]))
		{
			CBIT_SET(cd->mask, hashed_keys[1]);
			on_xition_cnt++;
		}
		if (!CBIT_TEST(cd->mask, hashed_keys[2]))
		{
			CBIT_SET(cd->mask, hashed_keys[2]);
			on_xition_cnt++;
		}
		if (!CBIT_TEST(cd->mask, hashed_keys[3]))
		{
			CBIT_SET(cd->mask, hashed_keys[3]);
			on_xition_cnt++;
		}
		statHistCount(&statCounter.cd.on_xition_count, on_xition_cnt);
	}
#endif
	cd->count++;
}
コード例 #9
0
ファイル: comm_select.c プロジェクト: carriercomm/myboxfs
static void
comm_select_icp_incoming(void)
{
    int nfds = 0;
    int fds[2];
    int nevents;
    icp_io_events = 0;
    if (theInIcpConnection >= 0)
	fds[nfds++] = theInIcpConnection;
    if (theInIcpConnection != theOutIcpConnection)
	if (theOutIcpConnection >= 0)
	    fds[nfds++] = theOutIcpConnection;
    if (nfds == 0)
	return;
    nevents = comm_check_incoming_select_handlers(nfds, fds);
    incoming_icp_interval += Config.comm_incoming.icp_average - nevents;
    if (incoming_icp_interval < 0)
	incoming_icp_interval = 0;
    if (incoming_icp_interval > MAX_INCOMING_INTERVAL)
	incoming_icp_interval = MAX_INCOMING_INTERVAL;
    if (nevents > INCOMING_ICP_MAX)
	nevents = INCOMING_ICP_MAX;
    statHistCount(&statCounter.comm_icp_incoming, nevents);
}
コード例 #10
0
ファイル: comm_select.c プロジェクト: carriercomm/myboxfs
/* Select on all sockets; call handlers for those that are ready. */
int
comm_select(int msec)
{
    fd_set readfds;
    fd_set pendingfds;
    fd_set writefds;
#if DELAY_POOLS
    BIT_ARRAY slowfds;
#endif
    PF *hdl = NULL;
    int fd;
    int maxfd;
    int num;
    int pending;
    int callicp = 0, callhttp = 0;
    int calldns = 0;
    int maxindex;
    int k;
    int j;
#if DEBUG_FDBITS
    int i;
#endif
    fd_mask *fdsp;
    fd_mask *pfdsp;
    fd_mask tmask;
    static time_t last_timeout = 0;
    struct timeval poll_time;
    double timeout = current_dtime + (msec / 1000.0);
    fde *F;
#if DELAY_POOLS
    BA_INIT(slowfds,SQUID_NUMFD);
#endif
    do {
#if !ALARM_UPDATES_TIME
	double start;
	getCurrentTime();
	start = current_dtime;
#endif
#if DELAY_POOLS
	BA_ZERO(slowfds);
#endif
	/* Handle any fs callbacks that need doing */
	storeDirCallback();
	if (commCheckICPIncoming)
	    comm_select_icp_incoming();
	if (commCheckDNSIncoming)
	    comm_select_dns_incoming();
	if (commCheckHTTPIncoming)
	    comm_select_http_incoming();
	callicp = calldns = callhttp = 0;
	maxfd = Biggest_FD + 1;
        xmemcpy(&readfds, &global_readfds,
            howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES);
        xmemcpy(&writefds, &global_writefds,
            howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES);
	/* remove stalled FDs, and deal with pending descriptors */
	pending = 0;
	FD_ZERO(&pendingfds);
	maxindex = howmany(maxfd, FD_MASK_BITS);
	fdsp = (fd_mask *) & readfds;
	for (j = 0; j < maxindex; j++) {
	    if ((tmask = fdsp[j]) == 0)
		continue;	/* no bits here */
	    for (k = 0; k < FD_MASK_BITS; k++) {
		if (!EBIT_TEST(tmask, k))
		    continue;
		/* Found a set bit */
		fd = (j * FD_MASK_BITS) + k;
		switch (commDeferRead(fd)) {
		case 0:
		    break;
		case 1:
		    FD_CLR(fd, &readfds);
		    break;
#if DELAY_POOLS
		case -1:
		    BA_SET(fd, slowfds);
		    break;
#endif
		default:
		    fatalf("bad return value from commDeferRead(FD %d)\n", fd);
		}
		if (FD_ISSET(fd, &readfds) && fd_table[fd].flags.read_pending) {
		    FD_SET(fd, &pendingfds);
		    pending++;
		}
	    }
	}
#if DEBUG_FDBITS
	for (i = 0; i < maxfd; i++) {
	    /* Check each open socket for a handler. */
#if DELAY_POOLS
	    if (fd_table[i].read_handler && commDeferRead(i) != 1) {
#else
	    if (fd_table[i].read_handler && !commDeferRead(i)) {
#endif
		assert(FD_ISSET(i, &readfds));
	    }
	    if (fd_table[i].write_handler) {
		assert(FD_ISSET(i, &writefds));
	    }
	}
#endif
	if (nreadfds + nwritefds == 0) {
	    assert(shutting_down);
#if DELAY_POOLS
            BA_FREE(slowfds);
#endif
	    return COMM_SHUTDOWN;
	}
	if (msec > MAX_POLL_TIME)
	    msec = MAX_POLL_TIME;
	if (pending)
	    msec = 0;
	for (;;) {
	    poll_time.tv_sec = msec / 1000;
	    poll_time.tv_usec = (msec % 1000) * 1000;
	    statCounter.syscalls.selects++;
	    num = select(maxfd, &readfds, &writefds, NULL, &poll_time);
	    statCounter.select_loops++;
	    if (num >= 0 || pending > 0)
		break;
	    if (ignoreErrno(errno))
		break;
	    debug(50, 0) ("comm_select: select failure: %s\n",
		xstrerror());
	    examine_select(&readfds, &writefds);
#if DELAY_POOLS
            BA_FREE(slowfds);
#endif
	    return COMM_ERROR;
	    /* NOTREACHED */
	}
	if (num < 0 && !pending)
	    continue;
	debug(5, num ? 5 : 8) ("comm_select: %d+%d FDs ready at %d\n",
	    num, pending, (int) squid_curtime);
	statHistCount(&statCounter.select_fds_hist, num);
	/* Check lifetime and timeout handlers ONCE each second.
	 * Replaces brain-dead check every time through the loop! */
	if (squid_curtime > last_timeout) {
	    last_timeout = squid_curtime;
	    checkTimeouts();
	}
	if (num == 0 && pending == 0)
	    continue;
	/* Scan return fd masks for ready descriptors */
	fdsp = (fd_mask *) & readfds;
	pfdsp = (fd_mask *) & pendingfds;
	maxindex = howmany(maxfd, FD_MASK_BITS);
	for (j = 0; j < maxindex; j++) {
	    if ((tmask = (fdsp[j] | pfdsp[j])) == 0)
		continue;	/* no bits here */
	    for (k = 0; k < FD_MASK_BITS; k++) {
		if (tmask == 0)
		    break;	/* no more bits left */
		if (!EBIT_TEST(tmask, k))
		    continue;
		/* Found a set bit */
		fd = (j * FD_MASK_BITS) + k;
		EBIT_CLR(tmask, k);	/* this will be done */
#if DEBUG_FDBITS
		debug(5, 9) ("FD %d bit set for reading\n", fd);
		assert(FD_ISSET(fd, &readfds));
#endif
		if (fdIsIcp(fd)) {
		    callicp = 1;
		    continue;
		}
		if (fdIsDns(fd)) {
		    calldns = 1;
		    continue;
		}
		if (fdIsHttp(fd)) {
		    callhttp = 1;
		    continue;
		}
		F = &fd_table[fd];
		debug(5, 6) ("comm_select: FD %d ready for reading\n", fd);
		if (NULL == (hdl = F->read_handler))
		    (void) 0;
#if DELAY_POOLS
		else if (BA_ISSET(fd, slowfds))
		    commAddSlowFd(fd);
#endif
		else {
		    F->read_handler = NULL;
		    commUpdateReadBits(fd, NULL);
		    hdl(fd, F->read_data);
		    statCounter.select_fds++;
		    if (commCheckICPIncoming)
			comm_select_icp_incoming();
		    if (commCheckDNSIncoming)
			comm_select_dns_incoming();
		    if (commCheckHTTPIncoming)
			comm_select_http_incoming();
		}
	    }
	}
	fdsp = (fd_mask *) & writefds;
	for (j = 0; j < maxindex; j++) {
	    if ((tmask = fdsp[j]) == 0)
		continue;	/* no bits here */
	    for (k = 0; k < FD_MASK_BITS; k++) {
		if (tmask == 0)
		    break;	/* no more bits left */
		if (!EBIT_TEST(tmask, k))
		    continue;
		/* Found a set bit */
		fd = (j * FD_MASK_BITS) + k;
		EBIT_CLR(tmask, k);	/* this will be done */
#if DEBUG_FDBITS
		debug(5, 9) ("FD %d bit set for writing\n", fd);
		assert(FD_ISSET(fd, &writefds));
#endif
		if (fdIsIcp(fd)) {
		    callicp = 1;
		    continue;
		}
		if (fdIsDns(fd)) {
		    calldns = 1;
		    continue;
		}
		if (fdIsHttp(fd)) {
		    callhttp = 1;
		    continue;
		}
		F = &fd_table[fd];
		debug(5, 5) ("comm_select: FD %d ready for writing\n", fd);
		if ((hdl = F->write_handler)) {
		    F->write_handler = NULL;
		    commUpdateWriteBits(fd, NULL);
		    hdl(fd, F->write_data);
		    statCounter.select_fds++;
		    if (commCheckICPIncoming)
			comm_select_icp_incoming();
		    if (commCheckDNSIncoming)
			comm_select_dns_incoming();
		    if (commCheckHTTPIncoming)
			comm_select_http_incoming();
		}
	    }
	}
	if (callicp)
	    comm_select_icp_incoming();
	if (calldns)
	    comm_select_dns_incoming();
	if (callhttp)
	    comm_select_http_incoming();
#if DELAY_POOLS
	while ((fd = commGetSlowFd()) != -1) {
	    F = &fd_table[fd];
	    debug(5, 6) ("comm_select: slow FD %d selected for reading\n", fd);
	    if ((hdl = F->read_handler)) {
		F->read_handler = NULL;
		commUpdateReadBits(fd, NULL);
		hdl(fd, F->read_data);
		statCounter.select_fds++;
		if (commCheckICPIncoming)
		    comm_select_icp_incoming();
		if (commCheckDNSIncoming)
		    comm_select_dns_incoming();
		if (commCheckHTTPIncoming)
		    comm_select_http_incoming();
	    }
	}
#endif
#if !ALARM_UPDATES_TIME
	getCurrentTime();
	statCounter.select_time += (current_dtime - start);
#endif
#if DELAY_POOLS
        BA_FREE(slowfds);
#endif
	return COMM_OK;
    }
    while (timeout > current_dtime);
    debug(5, 8) ("comm_select: time out: %d\n", (int) squid_curtime);
#if DELAY_POOLS
    BA_FREE(slowfds);
#endif
    return COMM_TIMEOUT;
}
#endif

static void
#if HAVE_POLL
comm_poll_dns_incoming(void)
#else
comm_select_dns_incoming(void)
#endif
{
    int nfds = 0;
    int fds[2];
    int nevents;
    dns_io_events = 0;
    if (DnsSocket < 0)
	return;
    fds[nfds++] = DnsSocket;
#if HAVE_POLL
    nevents = comm_check_incoming_poll_handlers(nfds, fds);
#else
    nevents = comm_check_incoming_select_handlers(nfds, fds);
#endif
    if (nevents < 0)
	return;
    incoming_dns_interval += Config.comm_incoming.dns_average - nevents;
    if (incoming_dns_interval < Config.comm_incoming.dns_min_poll)
	incoming_dns_interval = Config.comm_incoming.dns_min_poll;
    if (incoming_dns_interval > MAX_INCOMING_INTERVAL)
	incoming_dns_interval = MAX_INCOMING_INTERVAL;
    if (nevents > INCOMING_DNS_MAX)
	nevents = INCOMING_DNS_MAX;
    statHistCount(&statCounter.comm_dns_incoming, nevents);
}
コード例 #11
0
ファイル: comm_select.c プロジェクト: carriercomm/myboxfs
/* poll all sockets; call handlers for those that are ready. */
int
comm_poll(int msec)
{
#if FD_CONFIG
    struct pollfd *pfds = NULL;
#else
    struct pollfd pfds[SQUID_NUMFD];
#endif
#if DELAY_POOLS
    BIT_ARRAY slowfds;
#endif
    PF *hdl = NULL;
    int fd;
    unsigned int i;
    unsigned int maxfd;
    unsigned int nfds;
    unsigned int npending;
    int num;
    int callicp = 0, callhttp = 0;
    int calldns = 0;
    static time_t last_timeout = 0;
    double timeout = current_dtime + (msec / 1000.0);
#if FD_CONFIG
    pfds = xmalloc(sizeof(pfds[0])*SQUID_NUMFD);
#endif
#if DELAY_POOLS
    BA_INIT(slowfds,SQUID_NUMFD);
#endif
    do {
#if !ALARM_UPDATES_TIME
	double start;
	getCurrentTime();
	start = current_dtime;
#endif
	/* Handle any fs callbacks that need doing */
	storeDirCallback();
#if DELAY_POOLS
	BA_ZERO(slowfds);
#endif
	if (commCheckICPIncoming)
	    comm_poll_icp_incoming();
	if (commCheckDNSIncoming)
	    comm_poll_dns_incoming();
	if (commCheckHTTPIncoming)
	    comm_poll_http_incoming();
	callicp = calldns = callhttp = 0;
	nfds = 0;
	npending = 0;
	maxfd = Biggest_FD + 1;
	for (i = 0; i < maxfd; i++) {
	    int events;
	    events = 0;
	    /* Check each open socket for a handler. */
	    if (fd_table[i].read_handler) {
		switch (commDeferRead(i)) {
		case 0:
		    events |= POLLRDNORM;
		    break;
		case 1:
		    break;
#if DELAY_POOLS
		case -1:
		    events |= POLLRDNORM;
		    BA_SET(i, slowfds);
		    break;
#endif
		default:
		    fatalf("bad return value from commDeferRead(FD %d)\n", i);
		}
	    }
	    if (fd_table[i].write_handler)
		events |= POLLWRNORM;
	    if (events) {
		pfds[nfds].fd = i;
		pfds[nfds].events = events;
		pfds[nfds].revents = 0;
		nfds++;
		if ((events & POLLRDNORM) && fd_table[i].flags.read_pending)
		    npending++;
	    }
	}
	if (nfds == 0) {
	    assert(shutting_down);
#if DELAY_POOLS
            BA_FREE(slowfds);
#endif
#if FD_CONFIG
            xfree(pfds);
#endif
	    return COMM_SHUTDOWN;
	}
	if (npending)
	    msec = 0;
	if (msec > MAX_POLL_TIME)
	    msec = MAX_POLL_TIME;
	for (;;) {
	    statCounter.syscalls.polls++;
	    num = poll(pfds, nfds, msec);
	    statCounter.select_loops++;
	    if (num >= 0 || npending > 0)
		break;
	    if (ignoreErrno(errno))
		continue;
	    debug(5, 0) ("comm_poll: poll failure: %s\n", xstrerror());
	    assert(errno != EINVAL);
#if DELAY_POOLS
            BA_FREE(slowfds);
#endif
#if FD_CONFIG
            xfree(pfds);
#endif
	    return COMM_ERROR;
	    /* NOTREACHED */
	}
	debug(5, num ? 5 : 8) ("comm_poll: %d+%u FDs ready\n", num, npending);
	statHistCount(&statCounter.select_fds_hist, num);
	/* Check timeout handlers ONCE each second. */
	if (squid_curtime > last_timeout) {
	    last_timeout = squid_curtime;
	    checkTimeouts();
	}
	if (num <= 0 && npending == 0)
	    continue;
	/* scan each socket but the accept socket. Poll this 
	 * more frequently to minimize losses due to the 5 connect 
	 * limit in SunOS */
	for (i = 0; i < nfds; i++) {
	    fde *F;
	    int revents = pfds[i].revents;
	    fd = pfds[i].fd;
	    if (fd == -1)
		continue;
	    if (fd_table[fd].flags.read_pending)
		revents |= POLLIN;
	    if (revents == 0)
		continue;
	    if (fdIsIcp(fd)) {
		callicp = 1;
		continue;
	    }
	    if (fdIsDns(fd)) {
		calldns = 1;
		continue;
	    }
	    if (fdIsHttp(fd)) {
		callhttp = 1;
		continue;
	    }
	    F = &fd_table[fd];
	    if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) {
		debug(5, 6) ("comm_poll: FD %d ready for reading\n", fd);
		if (NULL == (hdl = F->read_handler))
		    (void) 0;
#if DELAY_POOLS
		else if (BA_ISSET(fd, slowfds))
		    commAddSlowFd(fd);
#endif
		else {
		    F->read_handler = NULL;
		    hdl(fd, F->read_data);
		    statCounter.select_fds++;
		    if (commCheckICPIncoming)
			comm_poll_icp_incoming();
		    if (commCheckDNSIncoming)
			comm_poll_dns_incoming();
		    if (commCheckHTTPIncoming)
			comm_poll_http_incoming();
		}
	    }
	    if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) {
		debug(5, 5) ("comm_poll: FD %d ready for writing\n", fd);
		if ((hdl = F->write_handler)) {
		    F->write_handler = NULL;
		    hdl(fd, F->write_data);
		    statCounter.select_fds++;
		    if (commCheckICPIncoming)
			comm_poll_icp_incoming();
		    if (commCheckDNSIncoming)
			comm_poll_dns_incoming();
		    if (commCheckHTTPIncoming)
			comm_poll_http_incoming();
		}
	    }
	    if (revents & POLLNVAL) {
		close_handler *ch;
		debug(5, 0) ("WARNING: FD %d has handlers, but it's invalid.\n", fd);
		debug(5, 0) ("FD %d is a %s\n", fd, fdTypeStr[F->type]);
		debug(5, 0) ("--> %s\n", F->desc);
		debug(5, 0) ("tmout:%p read:%p write:%p\n",
		    F->timeout_handler,
		    F->read_handler,
		    F->write_handler);
		for (ch = F->close_handler; ch; ch = ch->next)
		    debug(5, 0) (" close handler: %p\n", ch->handler);
		if (F->close_handler) {
		    commCallCloseHandlers(fd);
		} else if (F->timeout_handler) {
		    debug(5, 0) ("comm_poll: Calling Timeout Handler\n");
		    F->timeout_handler(fd, F->timeout_data);
		}
		F->close_handler = NULL;
		F->timeout_handler = NULL;
		F->read_handler = NULL;
		F->write_handler = NULL;
		if (F->flags.open)
		    fd_close(fd);
	    }
	}
	if (callicp)
	    comm_poll_icp_incoming();
	if (calldns)
	    comm_poll_dns_incoming();
	if (callhttp)
	    comm_poll_http_incoming();
#if DELAY_POOLS
	while ((fd = commGetSlowFd()) != -1) {
	    fde *F = &fd_table[fd];
	    debug(5, 6) ("comm_select: slow FD %d selected for reading\n", fd);
	    if ((hdl = F->read_handler)) {
		F->read_handler = NULL;
		hdl(fd, F->read_data);
		statCounter.select_fds++;
		if (commCheckICPIncoming)
		    comm_poll_icp_incoming();
		if (commCheckDNSIncoming)
		    comm_poll_dns_incoming();
		if (commCheckHTTPIncoming)
		    comm_poll_http_incoming();
	    }
	}
#endif
#if !ALARM_UPDATES_TIME
	getCurrentTime();
	statCounter.select_time += (current_dtime - start);
#endif
#if DELAY_POOLS
        BA_FREE(slowfds);
#endif
#if FD_CONFIG
        xfree(pfds);
#endif
	return COMM_OK;
    }
    while (timeout > current_dtime);
    debug(5, 8) ("comm_poll: time out: %ld.\n", (long int) squid_curtime);
#if DELAY_POOLS
    BA_FREE(slowfds);
#endif
#if FD_CONFIG
    xfree(pfds);
#endif
    return COMM_TIMEOUT;
}