Exemplo n.º 1
0
Arquivo: main.c Projeto: Issic47/libre
/**
 * Main polling loop for async I/O events. This function will only return when
 * re_cancel() is called or an error occured.
 *
 * @param signalh Optional Signal handler
 *
 * @return 0 if success, otherwise errorcode
 */
int re_main(re_signal_h *signalh)
{
	struct re *re = re_get();
	int err;

#ifdef HAVE_SIGNAL
	if (signalh) {
		(void)signal(SIGINT, signal_handler);
		(void)signal(SIGALRM, signal_handler);
		(void)signal(SIGTERM, signal_handler);
	}
#endif

	if (re->polling) {
		DEBUG_WARNING("main loop already polling\n");
		return EALREADY;
	}

	err = poll_setup(re);
	if (err)
		goto out;

	DEBUG_INFO("Using async I/O polling method: `%s'\n",
		   poll_method_name(re->method));

	re->polling = true;

#ifdef HAVE_ACTSCHED
	if (METHOD_ACTSCHED == re->method) {
		err = actsched_start();
		goto out;
	}
#endif

	re_lock(re);
	for (;;) {

		if (re->sig) {
			if (signalh)
				signalh(re->sig);

			re->sig = 0;
		}

		if (!re->polling) {
			err = 0;
			break;
		}

		err = fd_poll(re);
		if (err) {
			if (EINTR == err)
				continue;

#ifdef DARWIN
			/* NOTE: workaround for Darwin */
			if (EBADF == err)
				continue;
#endif

			break;
		}

		tmr_poll(&re->tmrl);
	}
	re_unlock(re);

 out:
	re->polling = false;

	return err;
}
Exemplo n.º 2
0
Arquivo: main.c Projeto: Issic47/libre
/**
 * Enter an 're' thread
 *
 * @note Must only be called from a non-re thread
 */
void re_thread_enter(void)
{
	re_lock(re_get());
}
Exemplo n.º 3
0
Arquivo: main.c Projeto: Issic47/libre
/**
 * Polling loop
 *
 * @param re Poll state.
 *
 * @return 0 if success, otherwise errorcode
 */
static int fd_poll(struct re *re)
{
	const uint64_t to = tmr_next_timeout(&re->tmrl);
	int i, n;
#ifdef HAVE_SELECT
	fd_set rfds, wfds, efds;
#endif

	DEBUG_INFO("next timer: %llu ms\n", to);

	/* Wait for I/O */
	switch (re->method) {

#ifdef HAVE_POLL
	case METHOD_POLL:
		re_unlock(re);
		n = poll(re->fds, re->nfds, to ? (int)to : -1);
		re_lock(re);
		break;
#endif
#ifdef HAVE_SELECT
	case METHOD_SELECT: {
		struct timeval tv;

		/* Clear and update fd sets */
		FD_ZERO(&rfds);
		FD_ZERO(&wfds);
		FD_ZERO(&efds);

		for (i=0; i<re->nfds; i++) {
			if (!re->fhs[i].fh)
				continue;

			if (re->fhs[i].flags & FD_READ)
				FD_SET(i, &rfds);
			if (re->fhs[i].flags & FD_WRITE)
				FD_SET(i, &wfds);
			if (re->fhs[i].flags & FD_EXCEPT)
				FD_SET(i, &efds);
		}

#ifdef WIN32
		tv.tv_sec  = (long) to / 1000;
#else
		tv.tv_sec  = (time_t) to / 1000;
#endif
		tv.tv_usec = (uint32_t) (to % 1000) * 1000;
		re_unlock(re);
		n = select(re->nfds, &rfds, &wfds, &efds, to ? &tv : NULL);
		re_lock(re);
	}
		break;
#endif
#ifdef HAVE_EPOLL
	case METHOD_EPOLL:
		re_unlock(re);
		n = epoll_wait(re->epfd, re->events, re->maxfds,
			       to ? (int)to : -1);
		re_lock(re);
		break;
#endif

	default:
		(void)to;
		DEBUG_WARNING("no polling method set\n");
		return EINVAL;
	}

	if (n < 0)
		return errno;

	/* Check for events */
	for (i=0; (n > 0) && (i < re->nfds); i++) {
		int fd, flags = 0;

		switch (re->method) {

#ifdef HAVE_POLL
		case METHOD_POLL:
			fd = i;
			if (re->fds[fd].revents & POLLIN)
				flags |= FD_READ;
			if (re->fds[fd].revents & POLLOUT)
				flags |= FD_WRITE;
			if (re->fds[fd].revents & (POLLERR|POLLHUP|POLLNVAL))
				flags |= FD_EXCEPT;
			if (re->fds[fd].revents & POLLNVAL) {
				DEBUG_WARNING("event: fd=%d POLLNVAL"
					      " (fds.fd=%d,"
					      " fds.events=0x%02x)\n",
					      fd, re->fds[fd].fd,
					      re->fds[fd].events);
			}
			/* Clear events */
			re->fds[fd].revents = 0;
			break;
#endif
#ifdef HAVE_SELECT
		case METHOD_SELECT:
			fd = i;
			if (FD_ISSET(fd, &rfds))
				flags |= FD_READ;
			if (FD_ISSET(fd, &wfds))
				flags |= FD_WRITE;
			if (FD_ISSET(fd, &efds))
				flags |= FD_EXCEPT;
			break;
#endif
#ifdef HAVE_EPOLL
		case METHOD_EPOLL:
			fd = re->events[i].data.fd;

			if (re->events[i].events & EPOLLIN)
				flags |= FD_READ;
			if (re->events[i].events & EPOLLOUT)
				flags |= FD_WRITE;
			if (re->events[i].events & EPOLLERR)
				flags |= FD_EXCEPT;

			if (!flags) {
				DEBUG_WARNING("epoll: no flags fd=%d\n", fd);
			}

			break;
#endif
		default:
			return EINVAL;
		}

		if (!flags)
			continue;

		if (re->fhs[fd].fh) {
#if MAIN_DEBUG
			fd_handler(re, fd, flags);
#else
			re->fhs[fd].fh(flags, re->fhs[fd].arg);
#endif
		}

		/* Check if polling method was changed */
		if (re->update) {
			re->update = false;
			return 0;
		}

		--n;
	}

	return 0;
}
Exemplo n.º 4
0
/**
 * Listen for events on a file descriptor
 *
 * @param fd     File descriptor
 * @param flags  Wanted event flags
 * @param fh     Event handler
 * @param arg    Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int fd_listen(int fd, int flags, fd_h *fh, void *arg)
{
	struct re *re = re_get();
	int err = 0;

	DEBUG_INFO("fd_listen: fd=%d flags=0x%02x\n", fd, flags);

	if (fd < 0) {
		DEBUG_WARNING("fd_listen: corrupt fd %d\n", fd);
		return EBADF;
	}

	if (flags || fh) {
		err = poll_setup(re);
		if (err)
			return err;
	}

	if (fd >= re->maxfds) {
		if (flags) {
			DEBUG_WARNING("fd_listen: fd=%d flags=0x%02x"
				      " - Max %d fds\n",
				      fd, flags, re->maxfds);
		}
		return EMFILE;
	}
	re_lock(re);
	/* Update fh set */
	if (re->fhs) {
		re->fhs[fd].flags = flags;
		re->fhs[fd].fh    = fh;
		re->fhs[fd].arg   = arg;
	}

	re->nfds = max(re->nfds, fd+1);
	re_unlock(re);
	switch (re->method) {

#ifdef HAVE_POLL
	case METHOD_POLL:
		err = set_poll_fds(re, fd, flags);
		break;
#endif

#ifdef HAVE_EPOLL
	case METHOD_EPOLL:
		if (re->epfd <= 0)
			return EBADFD;
		err = set_epoll_fds(re, fd, flags);
		break;
#endif
	default:
		break;
	}

	if (err) {
		if (flags && fh) {
			fd_close(fd);
			DEBUG_WARNING("fd_listen: fd=%d flags=0x%02x (%m)\n",
				      fd, flags, err);
		}
	}

	return err;
}