1 /* ioset select() backend for srvx
2 * Copyright 2002-2006 srvx Development Team
4 * This file is part of srvx.
6 * srvx is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 #include "ioset-impl.h"
28 #ifdef HAVE_SYS_SELECT_H
29 # include <sys/select.h>
32 #ifdef HAVE_SYS_SOCKET_H
33 # include <sys/socket.h>
36 extern int clock_skew;
37 static struct io_fd **fds;
38 static unsigned int fds_size;
39 static fd_set read_fds, write_fds;
42 ioset_select_init(void)
48 ioset_select_add(struct io_fd *fd)
50 if ((unsigned)fd->fd >= fds_size) {
51 unsigned int old_size = fds_size;
52 fds_size = fd->fd + 8;
53 fds = realloc(fds, fds_size*sizeof(*fds));
54 memset(fds+old_size, 0, (fds_size-old_size)*sizeof(*fds));
60 ioset_select_remove(struct io_fd *fd)
62 FD_CLR(fd->fd, &read_fds);
63 FD_CLR(fd->fd, &write_fds);
67 ioset_select_update(struct io_fd *fd)
73 ioset_select_cleanup(void)
79 #define debug_fdsets(MSG, NFDS, READ_FDS, WRITE_FDS, EXCEPT_FDS, SELECT_TIMEOUT) (void)0
82 debug_fdsets(const char *msg, int nfds, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *select_timeout) {
83 static const char *flag_text[8] = { "---", "r", "w", "rw", "e", "er", "ew", "erw" };
88 for (pos=ii=0; ii<nfds; ++ii) {
89 flags = (read_fds && FD_ISSET(ii, read_fds)) ? 1 : 0;
90 flags |= (write_fds && FD_ISSET(ii, write_fds)) ? 2 : 0;
91 flags |= (except_fds && FD_ISSET(ii, except_fds)) ? 4 : 0;
94 pos += sprintf(buf+pos, " %d%s", ii, flag_text[flags]);
96 gettimeofday(&now, NULL);
98 log_module(MAIN_LOG, LOG_DEBUG, "%s, at "FMT_TIME_T".%06ld:%s (timeout "FMT_TIME_T".%06ld)", msg, now.tv_sec, now.tv_usec, buf, select_timeout->tv_sec, select_timeout->tv_usec);
100 log_module(MAIN_LOG, LOG_DEBUG, "%s, at "FMT_TIME_T".%06ld:%s (no timeout)", msg, now.tv_sec, now.tv_usec, buf);
106 ioset_select_loop(struct timeval *timeout)
113 /* Set up read_fds and write_fds fdsets. */
117 for (nn=0; nn<fds_size; nn++) {
121 FD_SET(nn, &read_fds);
122 if (fd_wants_writes(fd))
123 FD_SET(nn, &write_fds);
126 /* Check for activity, update time. */
127 debug_fdsets("Entering select", max_fd+1, &read_fds, &write_fds, NULL, timeout);
128 select_result = select(max_fd + 1, &read_fds, &write_fds, NULL, timeout);
129 debug_fdsets("After select", max_fd+1, &read_fds, &write_fds, NULL, timeout);
130 now = time(NULL) + clock_skew;
131 if (select_result < 0) {
132 if (errno != EINTR) {
133 log_module(MAIN_LOG, LOG_ERROR, "select() error %d: %s", errno, strerror(errno));
139 /* Call back anybody that has connect or read activity and wants to know. */
140 for (nn=0; nn<fds_size; nn++) {
141 ioset_events(fds[nn], FD_ISSET(nn, &read_fds), FD_ISSET(nn, &write_fds));
146 struct io_engine io_engine_select = {
148 .init = ioset_select_init,
149 .add = ioset_select_add,
150 .remove = ioset_select_remove,
151 .update = ioset_select_update,
152 .loop = ioset_select_loop,
153 .cleanup = ioset_select_cleanup,