static void fdevent_process() {
    std::vector<pollfd> pollfds;
    for (auto it = g_poll_node_map.begin(); it != g_poll_node_map.end(); ++it) {
        pollfds.push_back(it->second.pollfd);
    }
    CHECK_GT(pollfds.size(), 0u);
    D("poll(), pollfds = %s", dump_pollfds(pollfds).c_str());
    int ret = TEMP_FAILURE_RETRY(poll(&pollfds[0], pollfds.size(), -1));
    if (ret == -1) {
        PLOG(ERROR) << "poll(), ret = " << ret;
        return;
    }
    for (auto& pollfd : pollfds) {
        if (pollfd.revents != 0) {
            D("for fd %d, revents = %x", pollfd.fd, pollfd.revents);
        }
        unsigned events = 0;
        if (pollfd.revents & POLLIN) {
            events |= FDE_READ;
        }
        if (pollfd.revents & POLLOUT) {
            events |= FDE_WRITE;
        }
        if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
            // We fake a read, as the rest of the code assumes that errors will
            // be detected at that point.
            events |= FDE_READ | FDE_ERROR;
        }
#if defined(__linux__)
        if (pollfd.revents & POLLRDHUP) {
            events |= FDE_READ | FDE_ERROR;
        }
#endif
        if (events != 0) {
            auto it = g_poll_node_map.find(pollfd.fd);
            CHECK(it != g_poll_node_map.end());
            fdevent* fde = it->second.fde;
            CHECK_EQ(fde->fd, pollfd.fd);
            fde->events |= events;
            D("%s got events %x", dump_fde(fde).c_str(), events);
            fde->state |= FDE_PENDING;
            g_pending_list.push_back(fde);
        }
    }
}
Exemple #2
0
/* Wrap around select */
int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout)
{
    int n, ret;
    int i, fd;
    struct timeval _timeo, *timeo = NULL;
    fd_set rfds, wfds, efds;
    int max_fd = -1;

    DEBUG("poll(");
    dump_pollfds(_pfd, _nfds, _timeout);
    DEBUG(")\n");

    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    FD_ZERO(&efds);

    n = 0;

    for (i = 0; i < _nfds; i++) {
        fd = _pfd[i].fd;
        _pfd[i].revents = 0;

        /* fd < 0, revents = 0, which is already set */
        if (fd < 0) continue;

        /* fd is invalid, revents = POLLNVAL, increment counter */
        if (fd >= NOFILE || files[fd].type == FTYPE_NONE) {
            n++;
            _pfd[i].revents |= POLLNVAL;
            continue;
        }

        /* normal case, map POLL* into readfds and writefds:
         * POLLIN  -> readfds
         * POLLOUT -> writefds
         * POLL*   -> none
         */
        if (_pfd[i].events & POLLIN)
            FD_SET(fd, &rfds);
        if (_pfd[i].events & POLLOUT)
            FD_SET(fd, &wfds);
        /* always set exceptfds */
        FD_SET(fd, &efds);
        if (fd > max_fd)
            max_fd = fd;
    }

    /* should never sleep when we already have events */
    if (n) {
        _timeo.tv_sec  = 0;
        _timeo.tv_usec = 0;
        timeo = &_timeo;
    } else if (_timeout >= 0) {
        /* normal case, construct _timeout, might sleep */
        _timeo.tv_sec  = _timeout / 1000;
        _timeo.tv_usec = (_timeout % 1000) * 1000;
        timeo = &_timeo;
    } else {
        /* _timeout < 0, block forever */
        timeo = NULL;
    }


    ret = select(max_fd+1, &rfds, &wfds, &efds, timeo);
    /* error in select, just return, errno is set by select() */
    if (ret < 0)
        return ret;

    for (i = 0; i < _nfds; i++) {
        fd = _pfd[i].fd;

        /* the revents has already been set for all error case */
        if (fd < 0 || fd >= NOFILE || files[fd].type == FTYPE_NONE)
            continue;

        if (FD_ISSET(fd, &rfds) || FD_ISSET(fd, &wfds) || FD_ISSET(fd, &efds))
            n++;
        if (FD_ISSET(fd, &efds)) {
            /* anything bad happens we set POLLERR */
            _pfd[i].revents |= POLLERR;
            continue;
        }
        if (FD_ISSET(fd, &rfds))
            _pfd[i].revents |= POLLIN;
        if (FD_ISSET(fd, &wfds))
            _pfd[i].revents |= POLLOUT;
    }

    return n;
}
Exemple #3
0
void httpd_main(void)
{
	int rv, n, t, accepting;
	time_t hours, last_time;

	accepting = 1;
	last_time = current_time = startuptime = time(0);
	hours = current_time / 3600;
	log_d("*** %s starting", server_version);
	while (gotsigterm == 0) {
		if (gotsighup) {
			gotsighup = 0;
			init_logs(0);
			if (debug)
				log_d("logs reopened");
		}
		if (gotsigusr1) {
			gotsigusr1 = 0;
			close_connections();
			log_d("connections closed");
		}
		if (gotsigusr2) {
			gotsigusr2 = 0;
			close_servers();
			log_d("servers closed");
		}
		if (gotsigchld) {
			gotsigchld = 0;
			reap_children();
		}
		if (gotsigquit) {
			gotsigquit = 0;
			debug = debug == 0;
			if (debug)
				log_d("debugging turned on");
			else
				log_d("debugging turned off");
		}
		if (gotsigwinch) {
			gotsigwinch = 0;
			log_d("performing internal dump");
			internal_dump();
		}
		n = 0;
		if (accepting && find_connection())
			n = setup_server_pollfds(n);
		n = setup_connection_pollfds(n);
		n = setup_child_pollfds(n, forked_connections.head);
		if (n == 0 && accepting && stats.nconnections == 0) {
			log_d("no more sockets to poll from");
			break;
		}
		t = accepting ? 60000 : 1000;
		if (debug)
			dump_pollfds(n, 0);
		rv = poll(pollfds, n, t);
		current_time = time(0);
		if (rv == -1) {
			if (errno != EINTR) {
				lerror("poll");
				break;
			} else {
				if (debug)
					log_d("poll interrupted");
				continue;
			}
		}
		if (debug)
			dump_pollfds(n, 1);
		if (current_time != last_time) {
			if (accepting == 0)
				accepting = 1;
			if (current_time / 3600 != hours) {
				hours = current_time / 3600;
				init_logs(0);
				if (debug)
					log_d("logs rotated");
			}
		}
		if (rv) {
			if (accepting && run_servers() == -1)
				accepting = 0;
			run_connections();
		}
		if (current_time != last_time) {
			cleanup_connections();
			last_time = current_time;
		}
	}
	log_d("*** shutting down");
}