ioloop-select.c revision 4d1a0d73d7dc03669b36f12a8af9978de361ad06
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher/*
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher ioloop-select.c : I/O loop handler using select()
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher Copyright (c) 2002 Timo Sirainen
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher Permission is hereby granted, free of charge, to any person obtaining
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher a copy of this software and associated documentation files (the
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher "Software"), to deal in the Software without restriction, including
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher without limitation the rights to use, copy, modify, merge, publish,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher distribute, sublicense, and/or sell copies of the Software, and to
524ceecc11f3d458eb3c1cf1489c3ff6ccb22226Jakub Hrozek permit persons to whom the Software is furnished to do so, subject to
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek the following conditions:
7797e361155f7ce937085fd98e360469d7baf1b6Jakub Hrozek
64a424ec1b268427822c646f7781e26e56c197f6Jakub Hrozek The above copyright notice and this permission notice shall be
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher included in all copies or substantial portions of the Software.
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7a14e8f66c0e932fe2954d792614a3b61d444bd1Jakub Hrozek IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher*/
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek#include "lib.h"
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek#include "ioloop-internal.h"
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek#ifdef IOLOOP_SELECT
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher#ifdef HAVE_SYS_SELECT_H
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher# include <sys/select.h> /* According to POSIX 1003.1-2001 */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher#endif
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher#include <sys/time.h>
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher#include <unistd.h>
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstruct ioloop_handler_data {
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher fd_set read_fds, write_fds;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher};
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagherstatic fd_set tmp_read_fds, tmp_write_fds;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallaghervoid io_loop_handler_init(struct ioloop *ioloop)
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek{
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher ioloop->handler_data =
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher p_new(ioloop->pool, struct ioloop_handler_data, 1);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher FD_ZERO(&ioloop->handler_data->read_fds);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher FD_ZERO(&ioloop->handler_data->write_fds);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher}
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallaghervoid io_loop_handler_deinit(struct ioloop *ioloop)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher{
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher p_free(ioloop->pool, ioloop->handler_data);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher}
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallaghervoid io_loop_handle_add(struct ioloop *ioloop, int fd, int condition)
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher{
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher i_assert(fd >= 0);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher if (fd >= FD_SETSIZE)
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher i_fatal("fd %d too large for select()", fd);
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (condition & IO_READ)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher FD_SET(fd, &ioloop->handler_data->read_fds);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (condition & IO_WRITE)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher FD_SET(fd, &ioloop->handler_data->write_fds);
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek}
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozekvoid io_loop_handle_remove(struct ioloop *ioloop, int fd, int condition)
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek{
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek i_assert(fd >= 0 && fd < FD_SETSIZE);
2ea6196484055397cc4bc011c5960f790431fa9dStephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (condition & IO_READ)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher FD_CLR(fd, &ioloop->handler_data->read_fds);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (condition & IO_WRITE)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher FD_CLR(fd, &ioloop->handler_data->write_fds);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher}
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher#define io_check_condition(fd, condition) \
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher ((((condition) & IO_READ) && FD_ISSET((fd), &tmp_read_fds)) || \
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher (((condition) & IO_WRITE) && FD_ISSET((fd), &tmp_write_fds)))
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallaghervoid io_loop_handler_run(struct ioloop *ioloop)
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher{
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher struct timeval tv;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct io *io, *next;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher unsigned int t_id;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher int ret, fd, condition;
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek
ea929f1b022fc2cb77dec89b0e12accef983ec85Jakub Hrozek /* get the time left for next timeout task */
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher io_loop_get_wait_time(ioloop->timeouts, &tv, NULL);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher memcpy(&tmp_read_fds, &ioloop->handler_data->read_fds, sizeof(fd_set));
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher memcpy(&tmp_write_fds, &ioloop->handler_data->write_fds,
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher sizeof(fd_set));
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher ret = select(ioloop->highest_fd + 1, &tmp_read_fds, &tmp_write_fds,
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher NULL, &tv);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (ret < 0 && errno != EINTR)
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher i_warning("select() : %m");
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* execute timeout handlers */
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher io_loop_handle_timeouts(ioloop);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (ret <= 0 || !ioloop->running) {
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher /* no I/O events */
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher return;
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher }
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher io_p = &ioloop->ios;
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher for (io = ioloop->ios; io != NULL && ret > 0; io = *io_p) {
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher if (io->destroyed) {
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher /* we were destroyed, and io->fd points to -1 now. */
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher io_destroy(ioloop, io);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher continue;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher }
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher i_assert(io->fd >= 0);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher fd = io->fd;
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher condition = io->condition;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher if (io_check_condition(fd, condition)) {
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher ret--;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher t_id = t_push();
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher io->callback(io->context);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (t_pop() != t_id)
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher i_panic("Leaked a t_pop() call!");
1008001f34abb42df75f840db17f14a83f0c21d4Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher if (io->destroyed) {
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher io_destroy(ioloop, io_p);
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher continue;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher }
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher }
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher io_p = &io->next;
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher }
65a9065538fd85e6ead925d344e6b421900eb8c2Jakub Hrozek}
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher#endif
6b0f9cd2ee601121cb7fe1d9ad8ebce782aa8f39Stephen Gallagher