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 3 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
;
40 static fd_set write_fds
;
41 static fd_set except_fds
;
44 ioset_select_init(void)
50 ioset_select_add(struct io_fd
*fd
)
52 if ((unsigned)fd
->fd
>= fds_size
) {
53 unsigned int old_size
= fds_size
;
54 fds_size
= fd
->fd
+ 8;
55 fds
= realloc(fds
, fds_size
*sizeof(*fds
));
56 memset(fds
+old_size
, 0, (fds_size
-old_size
)*sizeof(*fds
));
62 ioset_select_remove(struct io_fd
*fd
, int closed
)
64 FD_CLR(fd
->fd
, &read_fds
);
65 FD_CLR(fd
->fd
, &write_fds
);
66 FD_CLR(fd
->fd
, &except_fds
);
72 ioset_select_update(struct io_fd
*fd
)
78 ioset_select_cleanup(void)
85 debug_fdsets(const char *msg
, int nfds
, fd_set
*read_fds
, fd_set
*write_fds
, fd_set
*except_fds
, struct timeval
*select_timeout
) {
86 static const char *flag_text
[8] = { "---", "r", "w", "rw", "e", "er", "ew", "erw" };
91 for (pos
=ii
=0; ii
<nfds
; ++ii
) {
92 flags
= FD_ISSET(ii
, read_fds
) ? 1 : 0;
93 flags
|= FD_ISSET(ii
, write_fds
) ? 2 : 0;
94 flags
|= FD_ISSET(ii
, except_fds
) ? 4 : 0;
96 pos
+= sprintf(buf
+pos
, " %d%s", ii
, flag_text
[flags
]);
98 gettimeofday(&now
, NULL
);
100 log_module(MAIN_LOG
, LOG_DEBUG
, "%s, at %lu.%06lu:%s (timeout %lu.%06lu)", msg
, (unsigned long)now
.tv_sec
, (unsigned long)now
.tv_usec
, buf
, (unsigned long)select_timeout
->tv_sec
, (unsigned long)select_timeout
->tv_usec
);
102 log_module(MAIN_LOG
, LOG_DEBUG
, "%s, at %lu.%06lu:%s (no timeout)", msg
, (unsigned long)now
.tv_sec
, (unsigned long)now
.tv_usec
, buf
);
106 # define debug_fdsets(MSG, NFDS, READ_FDS, WRITE_FDS, EXCEPT_FDS, SELECT_TIMEOUT) (void)0
110 ioset_select_loop(struct timeval
*timeout
)
117 /* Set up read_fds and write_fds fdsets. */
120 FD_ZERO(&except_fds
);
122 for (nn
=0; nn
<fds_size
; nn
++) {
126 FD_SET(nn
, &read_fds
);
127 FD_SET(nn
, &except_fds
);
128 if (fd_wants_writes(fd
))
129 FD_SET(nn
, &write_fds
);
132 /* Check for activity, update time. */
133 debug_fdsets("Entering select", max_fd
+1, &read_fds
, &write_fds
, &except_fds
, timeout
);
134 select_result
= select(max_fd
+ 1, &read_fds
, &write_fds
, NULL
, timeout
);
135 debug_fdsets("After select", max_fd
+1, &read_fds
, &write_fds
, &except_fds
, timeout
);
136 now
= time(NULL
) + clock_skew
;
137 if (select_result
< 0) {
138 if (errno
!= EINTR
) {
139 log_module(MAIN_LOG
, LOG_ERROR
, "select() error %d: %s", errno
, strerror(errno
));
145 /* Call back anybody that has connect or read activity and wants to know. */
146 for (nn
=0; nn
<fds_size
; nn
++) {
147 ioset_events(fds
[nn
], FD_ISSET(nn
, &read_fds
) | FD_ISSET(nn
, &except_fds
), FD_ISSET(nn
, &write_fds
));
152 struct io_engine io_engine_select
= {
154 .init
= ioset_select_init
,
155 .add
= ioset_select_add
,
156 .remove
= ioset_select_remove
,
157 .update
= ioset_select_update
,
158 .loop
= ioset_select_loop
,
159 .cleanup
= ioset_select_cleanup
,